Need help in Sharepoint workflow - sharepoint

I am new to sharepoint development and i have task in hand to do. I need to add few lines of code for the following logic.
Need to check if previous title and new title of task items are same.
If Not, then query the Task list
Find all the items which contain the previous title
Update their titles.
Here is my Pseudocode:
public override void ItemUpdating(SPItemEventProperties properties)
{
try {
this.DisableEventFiring();
//Need to write my logic here
base.ItemUpdating(properties);
}
catch (Exception ex) {
}
finally {
this.EnableEventFiring();
}
}
Can somebody guide me how to write the code for the above mentioned logic? If you have any sample code's with similar logic, please share it. It will be helpful for me.
Thanks in Advance!

This code might help you out. Maybe you need to adapt it for your needs, but the properties you need to access are the same.
public override void ItemUpdating(SPItemEventProperties properties)
{
//this will get your title before updating
var oldName = properties.ListItem["Title"].ToString();
//and this will get the new title
var newName = properties.AfterProperties["Title"].ToString();
if (newName != oldName)
{
using (var site = new SPSite("http://yoursitename"))
using (var web = site.OpenWeb())
{
var list = web.Lists["Tasks"];
var items = list.Items.OfType<SPListItem>().Where(i => (string) i["Title"] == oldName);
foreach (var item in items)
{
item["Title"] = newName;
item.Update();
}
}
}
base.ItemUpdating(properties);
}

Related

Release invoice on new screen

I need your help.
I have created a new screen, where I am calling all invoices pending release.
I have problems to release, I send a message where you request (you want to release).
It shows me the infinite message.
Only once should you ask me, then you should go out and follow the normal process.
public ProcessDocNew()
{
// Acuminator disable once PX1008 LongOperationDelegateSynchronousExecution [Justification]
Document.SetProcessDelegate(
delegate (List<ARInvoice> list)
{
List<ARRegister> newlist = new List<ARRegister>(list.Count);
foreach (ARInvoice doc in list)
{
newlist.Add(doc);
}
ProcessDoc(newlist, true);
}
);
Document.SetProcessCaption(ActionsMensje.Process);
Document.SetProcessAllCaption(ActionsMensje.ProcessAll);
}
public virtual void ProcessDoc(List<ARRegister> list, bool isMassProcess)
{
string title = "Test";
string sms = "¿Stamp?";
var Graph = PXGraph.CreateInstance<ARInvoiceEntry>();
ARInvoice document = Document.Current;
PEFEStampDocument timbrar = new PEFEStampDocument();/*This is a class where it is, all my method*/
if (isMassProcess == true)
{
Document.Ask(title, sms, MessageButtons.YesNo, MessageIcon.Question);
{
PXLongOperation.StartOperation(Graph, delegate
{
timbrar.Stamp(document, Graph); /*here I have my release method*/
});
}
}
}
public static class ActionsMensje
{
public const string Process = "Process";
public const string ProcessAll = "Process All";
}
I await your comments
Only once should you ask me, then you should go out and follow the
normal process.
That is not how the processing pattern works. The process delegate is called for each record and is therefore not a valid location to display a message that should be shown only once.
You would need to add a custom action to achieve that behavior. The scenario you're looking for should be implemented with a processing filter checkbox and processing filter to comply with best practices:
Documentation on processing screens implementation is available here:
https://help-2019r2.acumatica.com/Help?ScreenId=ShowWiki&pageid=a007b57b-af69-4c0f-9fd1-f5d98351035f

Display a specific result using foreach in Dictionary C#

Problem that I'm unable to solve is that when I search a contact, if found than I need that contact to be the only output but it's displaying whole record. What should I do?
here is my code
namespace Telephone_Directory
{
class Program
{
public bool info()
{
Console.WriteLine("ENTER THE NAME TO BE SEARCHED");
Dictionary<string, uint> contact = new Dictionary<string, uint>();
contact.Add("usman", 03453648729);
contact.Add("Iqtiqa", 03159825052);
contact.Add("Aamir", 03343315412);
contact.Add("Ghous", 03323142783);
var items = from pair in contact
orderby pair.Value ascending
select pair;
string chk = Console.ReadLine();
if (contact.ContainsKey(chk))
{
foreach (KeyValuePair<string, uint> pair in contact)
{
Console.WriteLine("{0}: {1}", pair.Key, pair.Value);
} return true;
}
else
return false;
}
static void Main(string[] args)
{
Program ob =new Program();
bool a=ob.info();
if (a == true)
{
Console.WriteLine("Your contact is found successfully");
}
else
Console.WriteLine("Not found");
Console.ReadLine();
}
}
}
You are checking if the Contact is available but you are iterating over the whole collection as an output. So you can completely remove the first query (var item = ...) because it does not have any effect because you are not using it anywhere.
I would propose accessing everything directly by the Dictionary Key like this
uint srchNumber;
contact.TryGetValue(chk, out srchNumber);
if (srchNumber != null)
Console.WriteLine("{0}: {1}", chk, srchNumber);
this will get you what you want.
But I would suggest to change the implementation because a Dictionary may be not optimal if you will have multiple items with the same name because it only allows you to have every key once. Instead I would suggest to use something like SortedList> or List<...>. Then you may query all possible results with a LINQ-Statement like
var results = from c in contact select c where c.key == chk
this will get you all Key-Value-Pairs belonging to a certain name.
But it is a matter of what you are trying to achieve.

EventReceiver to Create folder sharepoint 2010

I have this event receiver c# class that I am trying to implement on a Sharepoint site. It did not work. I have deployed it from visual studio 2010 after it was build ok. Does anyone see what is the problem? Is the code ok? or is the problem on the SP? Thank you.
- here is the new code
using System;
using System.Security.Permissions;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Security;
using Microsoft.SharePoint.Utilities;
using Microsoft.SharePoint.Workflow;
namespace EventReceiverCFolder.EventReceiver1
{
/// <summary>
/// List Item Events
/// </summary>
public class EventReceiver1 : SPItemEventReceiver
{
/// <summary>
/// An item is being added.
/// </summary>
public override void ItemAdded(SPItemEventProperties properties)
{
try
{
if (properties.ListTitle == "CF") // list where the item was added
{ // if item was added to this list then create a folder on - Dlib - list
UpdateFolder(properties);
}
}
catch (Exception ex)
{
properties.Status = SPEventReceiverStatus.CancelWithError;
properties.ErrorMessage = ex.Message;
properties.Cancel = true;
}
}
private void UpdateFolder(SPItemEventProperties properties)
{
string foldername = properties.ListItem["Title"].ToString();
try
{
SPSecurity.RunWithElevatedPrivileges(delegate()
{
//inside RunWithElevatedPriviliges I need to open a new site (an elevated site)
using (SPSite site = new SPSite(properties.Web.Site.ID))
{
using (SPWeb web = site.OpenWeb())
{
web.AllowUnsafeUpdates = true;
SPList list = web.Lists.TryGetList("DLib"); // this is doc Library where the new folder will be created
//note that we are creating a list item, not a folder - a folder IS a list item
SPListItem createdFolder = list.Items.Add(list.RootFolder.ServerRelativeUrl, SPFileSystemObjectType.Folder, null);
if (createdFolder != null)
{
createdFolder["Name"] = foldername;
createdFolder.Update();
}
list.Update();
}
}
});
}
finally { }
}
}
}
Don't do this: SPUser privilegedAccount = properties.Web.AllUsers[#"SHAREPOINT\SYSTEM"];
Read up on using SPSecurity.RunWithElevatedPrivileges. See the MSDN documentation here.
Also don't do a using (SPSite... and inside the using block you try to get the web via SPContext.Current - that web won't be elevated anymore.
The correct way is something along these lines (I didn't try this, so it' just to give you an idea where you are headed):
private void UpdateFolder(SPItemEventProperties properties)
{
string foldername = properties.ListItem["Title"].ToString();
SPSecurity.RunWithElevatedPrivileges(delegate()
{
//inside RunWithElevatedPriviliges I need to open a new site (an elevated site)
using (SPSite site = new SPSite(properties.Web.Site.ID))
{
using (SPWeb web = site.OpenWeb())
{
web.AllowUnsafeUpdates = true;
SPList list = web.Lists.TryGetList("ListTitle"); //is that really the list title?
//note that we are creating a list item, not a folder - a folder IS a list item
SSPListItem createdFolder = list.Items.Add(list.RootFolder.ServerRelativeUrl, SPFileSystemObjectType.Folder, null);
if (newFolder != null)
{
createdFolder["Name"] = foldername;
createdFolder.Update();
}
list.Update();
}
}
});
}
Also try to debug your code, set breakpoints etc.
I had to get folder name like this:
string foldername = Convert.ToString(properties.AfterProperties["Title"]);
Did you try to debug it? try to debug and tell us what error you are getting.
BUT before you debug first use sharepoint manager to see if your event receiver is attached properly.
If you dont know how to debug sharepoint event receiver then please see this

SPListItem.Update Fails

Using the following block of code, the listItem.Update fails with a NullReferenceException:
SPWeb web = null;
SPList list = null;
SPListItem listItem = null;
try
{
SPSecurity.RunWithElevatedPrivileges(delegate()
{
using (SPSite site = new SPSite(this.SiteUrl))
{
web = site.OpenWeb();
list = web.Lists[this.ListName];
listItem = list.Items.Add();
listItem["Background"] = "foo";
}
}
);
listItem.Update();
}
catch
{
}
finally
{
web.Dispose();
}
If I move the listItem.Update() method inside of the anonymous delegate, I get "Operation is not valid due to the current state of the object."
Yes, I've combed through SO and have tried many permutations without success.
Any ideas?
Update:
After the first comment, I tried to remove the anonymous delegate from the code to see if it fared any better:
// store the selected item to pass between methods
public T SelectedItem { get; set; }
// set the selected item and call the delegate method
public virtual void Save(T item)
{
SelectedItem = item;
try
{
SPSecurity.RunWithElevatedPrivileges(SaveSelectedItem);
}
catch
{
}
}
public virtual void SaveSelectedItem()
{
if (SelectedItem != null)
{
using (SPSite site = new SPSite(this.SiteUrl))
{
using(SPWeb web = site.OpenWeb())
{
SPList list = web.Lists[this.ListName];
SPListItem listItem = list.Items.Add();
//UpdateListItem(listItem, SelectedItem);
listItem["Background"] = "foo";
listItem.Update();
}
}
}
}
And this still fails "Operation is not valid due to the current state of the object." In both code samples, it looks like site.Impersonating is false. I am using Windows Auth, and Impersonation in the web.config. This is running from the ASP.Net Development server.
I found an example from this site (blackninjasoftware). I create a reference to the site, grab its SystemAccount token and then create another reference to the site, using the admin token. It seemed a little hackish to me at first - but hey - I have a deadline.
Final working method body now looks like:
SPListItem new_item = null;
SPSite initialSite = new SPSite(this.SiteUrl);
using (var site = new SPSite(this.SiteUrl, initialSite.SystemAccount.UserToken))
{
// This code runs under the security context of the SHAREPOINT\system
// for all objects accessed through the "site" reference. Note that it's a
// different reference than SPContext.Current.Site.
using (var elevatedWeb = site.OpenWeb())
{
elevatedWeb.AllowUnsafeUpdates = true;
SPList list = elevatedWeb.Lists[this.ListName];
new_item = list.Items.Add();
UpdateListItem(new_item, item);
if (new_item != null)
{
new_item.Update();
}
}
}
initialSite.Dispose();

Updating the url of a navigation node in moss programatically

Can anyone see why this should not work:
SPSite topNavigationSite = new SPSite("http://moss");
SPWeb topNavigationWeb = topNavigationSite.OpenWeb();
SPNavigationNodeCollection topNavigationBarNodes = topNavigationWeb.Navigation.TopNavigationBar;
SPNavigationNode updateNode = topNavigationBarNodes.Navigation.GetNodeByUrl("/about");
updateNode.Url = "";
topNavigationWeb.Update();
I can see debugging that the url get's set to "" but when the page renders, the navigation still shows the url as /about/default.aspx
I'm running this in page_load and expected it to update the moss database with the new url value.
I know this is 3years old! but as there is no where online about updating a current url!
I had to do some debugging and this is what iv come up with! By the way I got the hint from
topNavigationWeb.Update();
indicating that its updating a list! hint hint!
a bit of background! I wanted to update the quick links from a list when they add, update and delete an item from the list! On my list I have two columns Title and URL!
I then created a project in VS 2010, its an event receiver that is connected only to that list (done in the elements.xml file)
within the .cs file I added item added, item deleting(not deleted ;) ) and item updated
public override void ItemAdded(SPItemEventProperties properties)
public override void ItemUpdated(SPItemEventProperties properties)
public override void ItemDeleting(SPItemEventProperties properties)
now within each method you can simply call this method!
add/update
public static void AddQuickLaunchItem(string header, string url, SPWeb web)
{
SPNavigationNodeCollection quickLaunch = web.Navigation.QuickLaunch;
// try to get quick launch header
SPNavigationNode nodeHeader =
quickLaunch.Cast<SPNavigationNode>().Where(n => n.Title == header).FirstOrDefault();
//if header not found create it
if (nodeHeader == null)
{
nodeHeader = quickLaunch.AddAsFirst(new SPNavigationNode(header, url,true));
}
else
{
web.AllowUnsafeUpdates = true;
nodeHeader = quickLaunch.Cast<SPNavigationNode>().Where(n => n.Title == header).First() ;
nodeHeader.Url = url;
web.AllowUnsafeUpdates = false;
}
nodeHeader.Update();
web.Update();
}
the first part is checking if the node exists using the title (header)! I'm comparing between what headers there are and from the list item:
SPNavigationNode nodeHeader =
quickLaunch.Cast<SPNavigationNode>().Where(n => n.Title == header).FirstOrDefault();
this part is the comparison:
n.Title == header
I'm getting these values (header and url / spweb) like so:
public static void AddQuickLaunchItem(string header, string url, SPWeb web)
the method that is calling the above would look like this:
private void addloopweblinks(SPSite siteCollection, SPItemEventProperties properties)
{
// Enumerate through each site and apply branding.
foreach (SPWeb web in siteCollection.AllWebs)
{
AddQuickLaunchItem(properties.ListItem["Title"].ToString(), properties.ListItem["URL"].ToString(), web);
}
}
and the above method is called within the itemadded and itemupdated ;) passing the values like so:
public override void ItemAdded(SPItemEventProperties properties)
{
using (SPSite siteCollection = new SPSite(properties.WebUrl))
{
if (siteCollection != null)
{
addloopweblinks(siteCollection, properties);
}
}
}
similar things can be done for the delete ;)
SPNavigationNode nodeHeader =
quickLaunch.Cast().Where(n => n.Title == header).FirstOrDefault();
that will get the node!
nodeHeader.delete();
nodeHeader.update();
that will delete the item!
so in your case what you need, I don't know if you noticed it was this part:
web.AllowUnsafeUpdates = true;
nodeHeader = quickLaunch.Cast<SPNavigationNode>().Where(n => n.Title == header).First() ;
nodeHeader.Url = url;
web.AllowUnsafeUpdates = false;
nodeHeader.Update();
web.Update();
as you can see what i mean by the hint! nodeHeader.Update(); didnt update the url, when debugging it does change but when i go to the update part it doesnt work :( and it clicked in i need web.AllowUnsafeUpdates = true; loool only becuse I experienced a similar situation before!
for you it would be:
using(SPSite topNavigationSite = new SPSite("http://moss"))
{
using(SPWeb topNavigationWeb = topNavigationSite.OpenWeb())
{
web.AllowUnsafeUpdates = true;
SPNavigationNodeCollection topNavigationBarNodes =topNavigationWeb.Navigation.TopNavigationBar;
SPNavigationNode updateNode = topNavigationBarNodes.Navigation.GetNodeByUrl("/about");
updateNode.Url = "";
updateNode.Update();
web.Update();
web.AllowUnsafeUpdates = false;
}
}
If the user doesnt have the sufficent rights than you need to encapsulate the above with runwithelevatedprivalages :) hope this helps :)
Have you tried:
updateNode.Update();
topNavigationWeb.Update();
It doesn't look like you are updating the SPNavigationNode object. (Note: you may not need the second Update call.)

Resources