Showing posts with label Event handler/ Item handler. Show all posts
Showing posts with label Event handler/ Item handler. Show all posts

Monday, April 23, 2012

Implement SharePoint 2010 Site event receivers


In SharePoint 2010 we now have a new type of receiver which is related to site. We now can track when a web is adding, provisioned, moving, moved, deleting and deleted.

All receivers that end with ing are synchronous and those which ends with ed are asynchronous.

So let us go ahead and explore some of the receiver types and try to understand how it works.

Open up visual studio 2010 and select SharePoint 2010 and select event receivers in the template type.



Connect with the site and select farm solution.



Select Web receivers from the list. Let us select these four options and explore them. Rest you can check on your own and let us know if you face any issue.



You then will be presented with four receivers.



Go ahead and add following code in each of them. Now build and deploy the solution. And now try creating site, and then delete the site.

public override void WebDeleting(SPWebEventProperties properties)
       {
           //This code actually triggers for sub sites that is being deleted. Hence we have taken reference of parent web to write the entry.

           SPList lstTracking = properties.Web.ParentWeb.Lists["Track Different Events"];

           properties.Web.ParentWeb.AllowUnsafeUpdates = true;

           SPListItem item = lstTracking.Items.Add();

           item["Title"] = "Deleting the Web";
          
           item.Update();

           properties.Web.ParentWeb.AllowUnsafeUpdates = false;
         
       }

       ///

       /// A site is being provisioned.
       ///

       public override void WebAdding(SPWebEventProperties properties)          
       {
          
           //This handler will trigger at the time of web being added as a sub site. Track Different Events list is in the parent site.

           SPList lstTracking = properties.Web.Lists["Track Different Events"];

           properties.Web.AllowUnsafeUpdates = true;

           SPListItem item = lstTracking.Items.Add();

           item["Title"] = "Adding the Web";

           item.Update();

           properties.Web.AllowUnsafeUpdates = false;

          
       }

       ///

       /// A site was deleted.
       ///

       public override void WebDeleted(SPWebEventProperties properties)
       {
           //This code actually triggers for sub sites that is deleted. Hence we have taken reference of parent web to write the entry by
           //instantiating SPSite. properties.Web returns null as web has been deleted by this time.

           SPSite site = new SPSite("");

           SPWeb web = site.AllWebs["ECMA"];

           SPList lstTracking = web.Lists["Track Different Events"];

           web.AllowUnsafeUpdates = true;

           SPListItem item = lstTracking.Items.Add();

           item["Title"] = "Web has been deleted";

           item.Update();

           web.AllowUnsafeUpdates = false;
       }

       ///

       /// A site was provisioned.
       ///

       public override void WebProvisioned(SPWebEventProperties properties)
       {
           //This code actually triggers for sub sites that is created. Hence we have taken reference of parent web to write the entry.          

           SPList lstTracking = properties.Web.ParentWeb.Lists["Track Different Events"];

           properties.Web.ParentWeb.AllowUnsafeUpdates = true;

           SPListItem item = lstTracking.Items.Add();

           item["Title"] = "Web has been provisioned";

           item.Update();

           properties.Web.ParentWeb.AllowUnsafeUpdates = false;
       }

We’ve created a site. So now we can see two entries in the list.




Now delete the sub site and we get this.






Thursday, February 24, 2011

Copy attachment from one list to another list

This is really interesting stuff because this topic not only covers how to copy attachment(s) from one list to another but also shows parent child relationship between lists.

I had a list and also related sub list, the idea was very simple I had to have one more field in the list which has column called ParentID.

I had attached event handler to the parent list and in the handler I was fetching the assigned to group. So I had to get all users from that group and assign it to each individual, but I also need to track that these all entries are for particular item from parent.

So I wrote a simple handler and in item adding event I copied same list item to all users of Assignedto field from parent in the another list.

All went well, another requirement came in, and if parent is updated then all child items in another list also should be updated. Idea was very simple, but this is tricky. Why tricky? Because if by mistake it is assigned to incorrect group and have to be assigned to two groups at a time, then the best way to do is Get the item id in ItemUpdated event and then fetch all Parent ID from child list and delete all list items and then re insert.

You might think why not to update? Well, I leave up to you. Think about the scenario which I have mentioned above of updating with two or more groups at a time, there can be couple of individuals as well. You need to update all these data. At the end, you will say, yes deleting all list items and reinserting is better. If you feel, updating is better. Leave your comments. I would love to ask you questions. :)

Another requirement came. If item from parent gets deleted, all child items from another list should also be deleted. Again the scenario is very simple, In ItemDeleting event, get the ID of the list item, find all those ParentID items from the child list and then delete those list items from another child list.

Now the challenging part came in, if I add or update and attach multiple attachments, it should also get copied over another list items with Parent ID.

I have already written my code in ItemAdding. I went ahead and wrote a code for getting list item’s attachment. But wait, the main part is you can never have attachments of list item in ItemAdding event because Item has not actually been inserted to the list. So in ItemAdding you can never get attachments.

So the idea was to change the code from ItemAdding to ItemAdded. And guess what, yes I found the attachments there in Item Added event.

o here is a sample code which demonstrate you how to copy list item attachments to another list item.

spWeb.AllowUnsafeUpdates = true;

foreach (string AttachName in EventItem.Attachments)
{

SPFile oSpFile =
EventItem.ParentList.ParentWeb.GetFile(EventItem.Attachments.UrlPrefix + AttachName);
item.Attachments.Add(AttachName, oSpFile.OpenBinary());

}

item.Update();

spWeb.AllowUnsafeUpdates = false;

Where EventItem is source list item and item is destination list item.

So it is very simple to copy attachments from one list item to another list item in event handler.

Wednesday, September 24, 2008

Custom alert in SharePoint

We all know one of the very good features in Moss is Alerts.

And default alert message is also very good.

But as usual we all need to create a custom alerts mail in our SharePoint system.
We may need some style change, header/footer/logo change and also some business logic before sending alert mail.

So here is the way to change default alert mail in SharePoint.

We had this requirement a long time ago but we are not able to do it but suddenly we came across the KB on Microsoft Support site which explain step by step how to do that. Here is the link for KB 948321.

We tried that code and it worked like a charm.
Here is the same code but with some logical comment added by us just to understand the things.
But we recommended that follow the steps from the same link above(KB 948321)
using System;
using System.Text;
using System.Web;
using System.Collections.Generic;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Utilities;


namespace SharePointKings.CustomWebParts
{
public class CustomAlert : IAlertNotifyHandler
{
#region IAlertNotifyHandler Members

public bool OnNotification(SPAlertHandlerParams ahp)
{
try
{
//find the site
SPSite site = new SPSite(ahp.siteUrl + ahp.webUrl);
//open the web
SPWeb web = site.OpenWeb();
//get the list that has been changed(modified)
SPList list = web.Lists[ahp.a.ListID];
//get the item that has been changed
SPListItem item = list.GetItemById(ahp.eventData[0].itemId);


//path to reach to that item
string FullPath = HttpUtility.UrlPathEncode(ahp.siteUrl + "/" + ahp.webUrl + "/" + list.Title + "/" + item.Name);
//path to reach to that list
string ListPath = HttpUtility.UrlPathEncode(ahp.siteUrl + "/" + ahp.webUrl + "/" + list.Title);
//path to reach to that web
string webPath = HttpUtility.UrlPathEncode(ahp.siteUrl + "/" + ahp.webUrl);

string build = "";

//eventType string will get that item is Added/Changed or deleted
string eventType = string.Empty;

if (ahp.eventData[0].eventType == 1)
eventType = "Added";
else if (ahp.eventData[0].eventType == 2)
eventType = "Changed";
else if (ahp.eventData[0].eventType == 3)
eventType = "Deleted";

//this way you can build your email body
//also you can apply the bussiness logic that which field to show
//change your highlighted words every thing you can do
build = "<style type=\"text/css\">.style1 { font-size: small; border: 1px solid #000000;" +
"background-color: #DEE7FE;}.style2 { border: 1px solid #000000;}</style></head>" +
"<p><strong>" + item.Name.ToString() + "</strong> has been " + eventType + "</p>" +
"<br> this is test by <strong>SharepointKings</strong><br> looks nice" +
"<table style=\"width: 100%\" class=\"style2\"><tr><td style=\"width: 25%\" class=\"style1\">" +
"<a href=" + webPath + "/_layouts/mysubs.aspx>Modify my Settings</a></td>" +
"<td style=\"width: 25%\" class=\"style1\"> <a href=" + FullPath + ">View " + item.Name + "</a></td>" +
"<td style=\"width: 25%\" class=\"style1\"><a href=" + ListPath + ">View " + list.Title + "</a></td>" +
" </tr></table>";

//title of the email
string subject = list.Title.ToString();
//over here sending mail is done by SPUtility so check the configuration
//of central admin for outgoing email.
SPUtility.SendEmail(web, true, false, ahp.headers["to"].ToString(), subject, build);
//we don't know why but we as per KB we have to return false.
return false;
}
catch (System.Exception ex)
{
return false;
}
}

#endregion
}
}


After completion of code follow the steps for register these codes in your site, again go to for KB 948321

Here is the overview what to do, this is not the steps to follow just an over view.

For that you need to generate copy of alertTemplates.xml file
Note: Do not directly modify the alertTemplates.xml file. Directly modifying this file is unsupported.Change the Properties tag in that xml with your solution’s assembly.
And use
stsadm -o updatealerttemplates <<with mentioned parameters>>
And restart the Windows SharePoint Services Timer service.

You done it man!!!

Sunday, August 24, 2008

How to get previous value of listitem in ItemUpdating event

Hi All,

We have event handlers assigned to the list. Lets say when item is added or updated we trigger the event and handle the event by writing our custom code.

The problem happens many times when you require to know that what was the previously entered value if you handle the updating event. Getting the earlier value (before modification done i.e before updated called) in updating is possible so that we come to know that what was the previous value and what is the new changed value of list item.

All you need to do is write a simple code mentioned below:

SPListItem item = properties.ListItem;

string strAmounr = string.Empty;

if (item["Amount"] != null)
{
strAmounr = item["Amount"].ToString();
}


The above code actually gives you the previous value of the Amount column.

Now let's get the new entered value in Amount column of the list.

string strNewAmount = properties.AfterProperties["Amount"].ToString();


Simple!!!! Now you have new value of Amount too. so just compare them and perform your steps.

That's it. your job is done.

Thursday, June 5, 2008

Difference between Synchronous and Asynchronous Events

The primary differences between Sync & Async event handlers are :

1) Synch Eve Handlers will work before the event is completed while AEH will fire after the event is completed.
2) SEH are mostly used to stop the event from completion in order to validate few things. It means you can cancel the event using SEH while it is not possible to cancel the event from AEH.
3) SEH methods has their method names ending with -ing while AEH method names will end with -ed. e.g. ItemAdding, ItemUpdating are SEH while ItemAdded, ItemUpdated are AEH methods.
4) SEH can be used to Add/Modify the values of list fields while using AEH its not possible as it fires after the completion of event.

Tuesday, June 3, 2008

Redirection from event handler

Scenario:
recently we have a requirement, for that we need to change default behavior of SharePoint.

Here is the requirement.
• While adding Item in the list, create sub site regarding that item.
• Redirect to the newly created site.
• Same case while updating item also.

Default behavior.
• After adding or updating item your SharePoint will redirect you to the page from where you come.
• Like in list if you adding item by clicking “New Item” from “alltems.aspx” SharePoint will redirect you back to the same page “allitems.aspx”.

How to do it?• Create an event receiver like ItemAdding and ItemUpdating for that List or library.
• In that event receiver, provision site programmatically.
• After provisioning new site, redirect user to newly created sub site using SPUtility.Redirect method. (need to include Microsoft.SharePoint.Utilities)

Roadblocks
• My first road block is that HttpContext is not available in event handler.
• To resolve this problem Check this
• Now after finding a way to get HttpContext we can use SPUtility.Redirect method but if we use it item is not added and your thread will redirect.
• And you’re other events (Asynchronous) like ItemAdded and ItemUpdated will not fire.

Solution
• To resolve this problem please check Code snippet below
public override void ItemAdding(SPItemEventProperties properties)
{

//perform validation if required.

// get the list which item to be added
SPSite objsite = new SPSite (properties.SiteId);
SPWeb objweb = objsite.OpenWeb (properties.RelativeWebUrl);
SPList objlist = objweb.Lists[properties.ListId];

//use this method to disable reoccurence of events.

DisableEventFiring();
SPListItem itemToAdd = objlist.Items.Add();

//add item to list

itemToAdd.Update();
EnableEventFiring();

// provision sub site and perform required action

//redirect it to your new destination like newly provisioned sub site or any other page you want.

SPUtility.Redirect(strNewresiractionUrl, SPRedirectFlags.Trusted,current);

}

I hope you got my problem and solution. With the help of this you can find your solution according to your requirement.

And thank you very much to Eric Bartels for his superb post which was helpful to resolve this problem.

Tuesday, May 20, 2008

How to hide a column of SharePoint list in different mode (Add / Edit / Display Mode)?

Most of the time we have requirement like that this field should be shown only in new mode or it should not be shown only in Edit mode not in new mode.

in simple word every one is asking the same question
"How to hide a column of SharePoint list in different mode (Add / Edit / Display Mode)?"

We can hide it in view by not to show in grid view but what to do if you do not want to see that field in Dispforms.aspx?

Here is the way how to do that.

Check the code snippet first

SPSite objSite = SPContext.Current.Site;
SPWeb objWeb = objSite.OpenWeb();
SPList objList = objWeb.Lists[“Name of the list”];
SPField objField = objList.Fields[“Name of the column”];


This SPField has following properties.

objField.ShowInDisplayForm //show in display mode(dispform.aspx)
objField.ShowInEditForm //show in edit mode(editform.aspx)
objField.ShowInListSettings //show in list setting page of list where u can set order or remove that field.
objField.ShowInNewForm //show in new form (newform.aspx)
objField.ShowInVersionHistory // displayed in the page for viewing list item versions. objField.ShowInViewForms //show in grid view


All the properties shows their setting meaning by their name.

Just set the properties you want and uodate field and list.

objField.Update();
objList.Update();


See the magic.

Another problem is after hiding column how to set its data?

In event handler / item handler you can use

properties.AfterProperties[“Internal name of that column”] = “assign text”;

You will get your result.
Only thing to keep in mind that
If column is hidden then u cannot retrieve its value.


Some time it will show error

“One or more field types are not installed properly. Go to the list settings page to delete these fields.”


If you get these error there is only two scenarios is there.
1) If you have any custom field then it was not properly installed.
2) If you have do not have the field with that name and you are assigning value to it.

Just do a due diligence and check this two scenarios and your error might be solved.

Thursday, May 8, 2008

HttpContext in eventhandler

First off all, i would like to thank Adil Baig to show Developers (specifically in MOSS) like us that thing like this can be done in first place.

I often heard that HttpContext is null in event handler and we cannot use session and Request.QueryString.
Here is the solution.
public class MyEventHandler: SPItemEventReceiver
{
HttpContext current;
public MyEventHandler()
{
current = HttpContext.Current;
}

public override void ItemAdding(SPItemEventProperties properties)
{
/// some thing went wrong so you need to cancel the event and redirect
}

With this Context you can find all the properties you want.
In SharePoint there is not any functionality for displaying our customized error page.
Like if for data validation in event/item handler we use
properties.ErrorMessage = “Opps... Not allowed”;
properties.Cancel = true;

And validation message displayed in SharePoint error Page which looks error in application.
But with this Context you can use to redirect to any of your custom or any out of the box Page.
SPUtility.Redirect(Url, SPRedirectFlags.Default, current);

HttpContext is available only in synchronous event like ItemAdding and ItemUpdating.

More Info Click Here

Wednesday, May 7, 2008

Save Conflict / Recursive call of event handler / Update item in item updating and adding

Microsoft.SharePoint.SPException: Save Conflict
Your changes conflict with those made concurrently by another user.
If you want your changes to be applied, click back in your Web browser, refresh the page, and resubmit your changes.

This post is also solution of
Recursive call of event handler and update item in item updating and adding

Once I was suffering from “Save Conflict” error while updating a List item.
This thing happens when to achieve two of my business requirements.


Scenario 1:
In my scenario I have a workflow attached with the list. While adding or updating item from this list, by default workflow is attached to the list. Now as per my requirement. On workflow activated and on task generated again I want to fill one field in the same list. I got “Save conflict” error while updating that list item from workflow.

Scenario 2:
In one of my list in item handler I’m creating a sub site with the Title of the item. What I want to do is that in item added I want to update the list field. But while updating I’m having this “save conflict” error.

So in both the case what I found was that when we are calling
ListItem.Update();
method, list’s ItemUpdating event fires and again all the procedure go in to the recursive loop.
To solve this problem try one of these code snippets.

1) (useful while updating List/web from outer side of the scoop of that web or site)
web.AllowUnsafeUpdates = true;
ListItem.SystemUpdate(false);
or
ListItem.Update();
web.AllowUnsafeUpdates = false;
//must set AllowUnsafeUpdates to false if we are set it to true.

2) (Usefull in from updating Item from event handler)
Item[FieldName] = FieldValue;
this.DisableEventFiriing();
item.SystemUpdate(false);
or
item.Update();
this.EnableEventFiring();
//must enable event firing if we are disable it


hopefully this post will help you guys for solving your problem.

Cheers.




Share your SharePoint Experiences with us...
As good as the SharePointKings is, we want to make it even better. One of our most valuable sources of input for our Blog Posts comes from ever enthusiastic Visitors/Readers. We welcome every Visitor/Reader to contribute their experiences with SharePoint. It may be in the form of a code stub, snippet, any tips and trick or any crazy thing you have tried with SharePoint.
Send your Articles to sharepointkings@gmail.com with your Profile Summary. We will Post them. The idea is to act as a bridge between you Readers!!!

If anyone would like to have their advertisement posted on this blog, please send us the requirement details to sharepointkings@gmail.com