Thursday, August 28, 2008

Attaching SPItemEventReceiver with a List Type

In my last post I have talked about writing an SPItemEventReceiver for fetching a workflow instance out of a Task item in a Task List type. Next step that comes to our mind is how we can attach this event receiver with a List. There are two ways in which you can attach your event receiver to a list type. One is through a feature: in elements.xml file you can write CAML and have Receiver attributes. another way is by using object model. I will explain you both the ways:

1) Feature way:

Create a feature.xml in the normal way as you do for any other feature. Here is the example:



"<"!--Created by Kunal Kochhar at 18/08/2008 10:21:18 AM--">"
"<"Feature Id="66D0E36C-4D48-46D0-90E9-7BFGHFBE4E3C" Title="Item receiver attacher" Description="This feature will attach event handler to a task item generated by Disposition workflow" Version="1.0.0.0" Scope="Web" Hidden="false" ImageUrl="CustomBranding.gif" xmlns="http://schemas.microsoft.com/sharepoint/"">"
"<"ElementManifests">"
"<"ElementManifest Location="elements.xml" /">"
"<"/ElementManifests">"
"<"/Feature">"



Now write the elements.xml file. This file will have Receivers tag. Read here more about Receivers element:

http://msdn.microsoft.com/en-us/library/ms431081.aspx

Let me show you the elements file:

'<'elements xmlns="http://schemas.microsoft.com/sharepoint/"'>'
'<'Receivers ListTemplateId="107"'>'
'<'Receiver'>'
'<'Name'>'TaskAdded'<'/Name'>'
'<'Type'>'ItemAdded'<'/Type'>'
'<'SequenceNumber'>'10043'<'/SequenceNumber'>'
'<'Assembly'>'assemblyname, [full four part]'<'/Assembly'>'
'<'Class'>'namespacename.classname'<'/Class'>'
'<'Data'>''<'/Data'>'
'<'Filter'>''<'/Filter'>'
'<'/Receiver'>'
'<'/Receivers'>'
'<'/Elements'>'



As you can see I am saying ListTemplateId=107 in the Receivers element. This id is the List Template Id for Tasks list type. You can refer to more list template ids here: http://msdn.microsoft.com/en-us/library/ms431081.aspx
Once you deploy and activate this feature on web it will attach your required event handler with all the existing tasks lists or any new ones that you create.

2) Lets see the second approach which is through code. The SPWeb object exposes list templates and contenttypes collections. You can retreive the required list template type and content type and can add your eventreceiver assembly in their eventreceivers collection. Here is an example to add it to a content type:

SPWeb web = SPContext.Current.Web;
SPContentType ct = web.ContentTypes["Tasks"];
SPEventReceiverDefinition receiverDef = ct.EventReceivers.Add();
receiverDef.Name = "Custom_ItemAdded";
receiverDef.Type = SPEventReceiverType.ItemAdded;
receiverDef.SequenceNumber = 10012;
receiverDef.Assembly = "assembly, [full four part assembly details]";
receiverDef.Class = "namespacename.classname";
receiverDef.Update();

I hope this will help some of you. If you have any queries in relation to this then please feel free to write to me.

2 comments:

Deepak Chawla said...

Hi Kunal,

I have added custom event handlers for reservation list using caml. In element.xml i have specified receiver tag as 'Receivers ListTemplateId="100"' This templateid is for generic lists.

it has attached event handler to my reservation list but it has also attached event handler with resource type list & resources lists.

what i might have doen wrong & what is it's solution.

Thanks,
Deepak

{-_-} said...

Im having a problem with AfterProperties for SPFieldType.User field which return unexpected result.

public class ItemEventReceiver : SPItemEventReceiver
{
public override void ItemAdded(SPItemEventProperties properties)
{
SPItemEventDataCollection cListItemAfter = properties.AfterProperties;
...
}
}

the cListItemAfter hash table always contains user field value with either of these values and it keeps changing and not fixed to either one:

> 1
> -1;#DOMAIN\Account
> 1;#DOMAIN\Account

any thoughts on this issue?


It's a custom list. This solution only works if the item has been created.

For a new item this solution return null on properties.ListItem.

There are no alternating values using this method, but it does not work for a new form.

Another thing that i noticed is that the hash table of AfterProperties sometimes contains exact amount of actual fields and sometimes less than what is supposed to be for unknown reason.

I need to use the same type of variable of SPItemEventDataCollection or SPListItem (either one) so that the variable contains all the current fields for both new and edit form.