Tuesday, April 30, 2013

SharePoint 2010 - Creating an Event Receiver


In the previous post, we had an overview of Event Receivers. In this post we will actually create an event receiver to understand the basic functionality.

Objective
We need to accomplish the following tasks for this demo:
1) Create a custom list named 'Customers' with just name and address.
2) Create a custom list named 'Orders' and add Customer's 'Title' as a lookup field.
3) Add an event handler to retrieve the Customer's 'Address' and save it as 'Shipping address' in the Orders list in the ItemAdding event.

Steps for creating the event receiver
Following are the steps for creating the Event Receiver.

1) Create a custom list named "Customers" with the fields as shown in the following figure.

2) Enter some sample data in the "Customers" list.

3) Create another custom list named "Orders" with the fields as shown in the following figure. Make sure "Title" field from "Customers" List is added as lookup field in this list.


4) Create sample data for Orders list and leave the "ShippingAddress" filed blank.

5) Right now "ShippingAddress" field remains blank.

We need to target that whenever a new item is created, the "ShippingAddress" field should be updated with the value from "Address" field in the "Customers" List.

6) Open Visual Studio 2010 and create a new project named "EventReceiverDemo". Add a new feature named "OrderProcess" scoped as web.

7) Right click on the solution and add a new EventReceiver named "OrdersEventReceiver" as follows.

8) You will be prompted with a dialogue for choosing the List Type (eg: Custom list, Announcement etc) and the event that will bind with this list. Choose "An item is being added".

9) A new class is created named OrdersEventReceiver inherited from SPItemEventReceiver base class which contains the ItemAdding Event.

10) Added the following code in the ItemAdding Event. Its just a simple code for getting the Customer Name (ID;#Title format) from the current item being saved. Using the 'Id' we get the details from the "Customers" List and update in the "ShippingAddress" filed of the current.

public class OrdersEventReceiver : SPItemEventReceiver
    {
       public override void ItemAdding(SPItemEventProperties properties)
       {
           base.ItemAdding(properties);
           //Elevate the permissions to Admin level for performing this operation.
           SPSecurity.RunWithElevatedPrivileges(delegate {
               
               //Get the selected Customer's Look up Title which is in the form of "1;#NealMukundan".             
               SPListItem CurrentItem = properties.ListItem;
               String strCustomer = CurrentItem["Customer"].ToString();
               
               //Get the selected Customer's ID using Substring
               int startPos = 0;
               int endPos = CurrentItem["Customer"].ToString().IndexOf(";#");
               int Cust_ID = Convert.ToInt32(strCustomer.Substring(startPos, endPos));
 
               //Get the list items from 'Customers' List using Customer ID.
               SPWeb oWeb = properties.Web;
               SPList oList = oWeb.Lists["Customers"];
               SPListItem Customers = oList.GetItemById(Cust_ID);
 
               //Assign the 'Address' from Customers List to the 'Shipping Address' in the Current Item.
               CurrentItem["ShippingAddress"] = Customers["Address"];
 
               //Update the current item
               oWeb.AllowUnsafeUpdates = true;
               oWeb.Update(); 
               oWeb.AllowUnsafeUpdates = false;           
           });
       }
    }
11) Now that we have created the Event Receiver, we must bind it to the 'Orders' List using a Feature Receiver.

12) Right click on the Feature and an new Feature Receiver as follows.

13) Open the 'Elements.xml' linked to the 'OrdersEventReceiver.cs' file since we will use this data to override the Feature Receiver Events.

14) Added the following code in the FeatureActivated event. We need to create an event receiver definition using the SPEventReceiverDefinition class. You can get the values for definition from the XML file mentioned in the previous step.
public override void FeatureActivated(SPFeatureReceiverProperties properties)
        {
            SPSecurity.RunWithElevatedPrivileges(delegate {
                //Get the List instance from the Fetaure Properties
                SPWeb oWeb = (SPWeb)properties.Feature.Parent;
                SPList oList = oWeb.Lists["Orders"];
                //Add event receiver definition to the 'Orders' List
                SPEventReceiverDefinition oDefinition = oList.EventReceivers.Add();
                oDefinition.Assembly = Assembly.GetExecutingAssembly().FullName;
                oDefinition.Class = "EventReceiverDemo.OrdersEventReceiver";
                oDefinition.Type = SPEventReceiverType.ItemAdded;
                oDefinition.SequenceNumber = 10005;
                oDefinition.Name = "OrdersEventReceiverItemAdding";
                oDefinition.Data = null;
                oDefinition.Update();
            });            
        }
15) Added the following code in the FeatureDeactivating event. We need to remove the event receiver definition from SPEventReceiverDefinitionCollection.
public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
        {
            SPSecurity.RunWithElevatedPrivileges(delegate {
                //Get the List instance from the Fetaure Properties
                SPWeb oWeb = (SPWeb)properties.Feature.Parent;
                SPList oList = oWeb.Lists["Orders"];
                //Remove event receiver definition from 'Orders' List
                SPEventReceiverDefinitionCollection oColl = oList.EventReceivers;
                foreach (SPEventReceiverDefinition oDefinition in oColl)
                {
                    if (oDefinition.Name == "OrdersEventReceiverItemAdding")
                    {
                        oColl[oDefinition.Id].Delete();
                        break;
                    }
                }
            });                        
        }
16) Now deploy the solution and activate the "OrderProcess" Feature.

17) Go to the "Orders" list and create a new item.

18) As shown in the following figure, the "ShippingAddress" field will be automatically updated.

19) If the "OrderProcess" Feature is deactivated then the event receiver will be removed and the "ShippingAddress" field will no longer be updated.

Hope this post gives you a better idea about Event Receivers in SharePoint 2010.

Friday, April 26, 2013

SharePoint 2010 - Event Receivers Overview

Overview
Event receivers are classes that allow you to respond to events that occur to SharePoint items such as lists or list items.

For example, if a project manager needs to be alerted when new documents or files are added to a given document library, you could write event receiver code to send an e-mail notification to the project manager, and then bind that code to the item-addition action on the document library.

Commonly used Event Receivers
1) SPItemEventReceiver: Event receivers related to single SharePoint items (SPListItem).
2) SPListEventReceiver: Event receivers for trapping events related to list instances.
3) SPWebEventReceiver: Event receivers that catch events raised by webs.
4) SPWorkflowEventReceiver: Event Receivers related to workflows instances.
5) SPEmailEventReceiver: Event receivers that trigger whenever an e-mail–enabled document library receives an e-mail message.

Operations available in Event Receivers

Object
Operations
Site collectionDeletion
WebCreation
URL modification
Deletion
ListCreation
Deletion
Received an e-mail message
FieldCreation
Update
Deletion
ItemCreation
Update
Deletion
Check in
Check out
File movement
File conversion
Adding attachment
Deleting attaching


Synchronous (Before) Events
The Before events are those that happen just after the event occurred, but before SharePoint writes any data to the SharePoint content database. Such events are useful for custom validation, rules checking, and cancelation of users’ actions.

Asynchronous (After) Events
The After events are those that happen after SharePoint commits the data to the SharePoint content database. These After event handlers cannot cancel the current action/operation, but they are guaranteed to execute only after specific actions.

Event Receiver Base Class
All of these receiver base classes (except for SPEmailEventReceiver and SPFeatureReceiver) inherit from a common base class named SPEventReceiverBase, which provides the very basic infrastructure for events management.
In addition, all of these classes provide a set of virtual methods that developers should override when implementing events.
i) Before events run in the same process and thread as the current action.
ii) After events by default run in a background thread; however, you can force them to run synchronously, that means within the same process and thread of the current action.

Event Binding
Event binding (also known as event registration) can be done by using the server object model or by using Feature XML. The following sections provide detailed information about binding events in SharePoint Foundation.

Event Cancellation
Event cancellation enables you to cancel an event receiver operation in a Before event prior to the conclusion of the action. For example, we can write some code in the ItemAdding event receiver that cancels the action of adding the item. So when the user tries to add an item, the operation is cancelled and the item is not added to the list. When the operation is cancelled, be sure to show the user an error message or provide a custom error message by redirecting the user to a specific URL.

Event Receiver Sequence
The event receiver sequence specifies the order in which an event receiver is executed in cases where an event triggers multiple event receivers. For example, if you have two ItemAdded event receivers bound to the same list (one from Assembly "1" and the other from Assembly "2"), the event receiver that is bound with a lower sequence number is executed first. A practical example is adding an event receiver to a system list that already has a system event receiver bound to it. In that case, you assign the new event receiver a higher sequence number.

Event receiver base classes and supported events
Following is the list of Event Receiver base classes and the events supported by them:
Event receiver base classAvailable event host typesSupported events
SPWebEventReceiverSPSiteSiteDeleting
SPWebSiteDeleted
WebAdding
WebProvisioned
WebDeleting
WebDeleted
WebMoving
WebMoved
SPListEventReceiver (lists)SPSiteListAdding
SPWebListAdded
ListDeleting
ListDeleted
SPListEventReceiver (fields)SPSiteFieldAdding
SPWebFieldAdded
SPListFieldDeleting
SPContentTypeFieldDeleted
FieldUpdating
FieldUpdated
SPItemEventReceiverSPSiteItemAdding
SPWebItemAdded
SPListItemDeleting
SPContentTypeItemDeleted
ItemUpdating
ItemUpdated
ItemFileConverted
ItemFileMoving
ItemFileMoved
ItemCheckingIn
ItemCheckedIn
ItemCheckingOut
ItemCheckedOut
ItemAttachmentAdding
ItemAttachmentAdded
ItemAttachmentDeleting
ItemAttachmentDeleted
SPEmailEventReceiverSPSiteEmailReceived
SPWeb
SPList
SPWorkflowEventReceiverSPSiteWorkflowStarting
SPWebWorkflowStarted
SPListWorkflowCompleted
SPContentTypeWorkflowPostponed

I hope this post will give you an overview about Event Receivers in SharePoint 2010! In the next post we see how to create an Event Receiver and bind it to a list.

Reference:
2) Microsoft SharePoint 2010 Developer Reference, by Paolo Pialorsi - Book.

Wednesday, April 24, 2013

SharePoint 2010 - Creating a Feature Receiver

In the previous post we discussed about Feature Receivers in SharePoint 2010. In this post we will create a sample feature receiver to understand its basic functionality.

Objective
1) We will create a new feature which will have an event receiver attached to it.
2) Whenever this feature is activated, a new list named "Sales" will be created.
3) Upon de-activating the feature the "Sales" list will automatically get deleted.

Steps for creating the Feature Receiver
1) Create an empty SharePoint 2010 project named "FeatureReceiverDemo".
2) Add a Feature named "FeatureReceiverDemo" (It can be any name).
3) Right click on the new feature and select "Add Event Receiver" as shown in the figure below.

4) A new class file name "FeatureReceiverDemo.EventReceiver.cs" will be created which has the code for overriding the feature receiver events in commented format.

5) As discussed in the previous post, a feature can have the following events which can be captured and functionalities can be attached to it:-
i) Feature Activation: Occurs when a feature has been activated
ii) Feature Deactivating: Occurs while a feature is deactivating
iii) Feature Installation: Occurs when a feature has been installed
iv) Feature Uninstalling: Occurs while a feature is un-installing
v) Feature Upgrading: Occurs while a feature is upgrading

6) To achieve our objective we will override the FeatureActivated event and add the code for creating a new list named "Sales" whenever this event is fired. Following is the code.
public override void FeatureActivated(SPFeatureReceiverProperties properties)
        {
            SPSite site = properties.Feature.Parent as SPSite;
            if (site != null)
            {
                SPWeb web = site.RootWeb;
                try
                {
                    SPList targetList = web.Lists["Sales"];
                }
                catch (ArgumentException)
                {
                    Guid listId = web.Lists.Add("Sales",
                    "Sales List created through code"SPListTemplateType.Events);
                    SPList list = web.Lists[listId];
                    list.OnQuickLaunch = true;
                    list.Update();
                }
            }
 
        }

7) Similarly we will override the FeatureDeactivating event and add the code for deleting the list named "Sales" whenever this event is fired. Following is the code.
public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
        {
            SPSite site = properties.Feature.Parent as SPSite;
            if (site != null)
            {
                SPWeb web = site.RootWeb;
                try
                {
                    SPList list = web.Lists["Sales"];
                    list.Delete();
                }
                catch (ArgumentException)
                {
                }
            }
 
        }
8) Deploy the solution.

9) Go to Site Settings->Site Collection Features. Activate the feature "Feature Receiver Demo".


10) You will notice that a list named "Sales" has been created which is also available in Quick Launch.

11) Click on the "Sales" link on quick launch to view the list. Based on your preference  you can choose any template for your list using "SPListTemplateType" in the code.

12) Now go back to Site Settings->Site Collection Features. De-activate the feature "Feature Receiver Demo".

13) You will notice that the list named "Sales" has been deleted which is also removed from the Quick Launch.

I hope that this sample will provide a broader idea about the usage of event receivers.

References
1) Microsoft SharePoint 2010 Developer Reference, by Paolo Pialorsi - Book.

Monday, April 22, 2013

SharePoint 2010 - Feature Receiver Overview

Feature Receivers
A feature receiver is a class which can execute custom code through SharePoint object model whenever a particular feature life cycle related events occurs.

Feature Receiver Events
A feature receiver can trap the following events:
1) Feature Activation: Occurs when a feature has been activated
2) Feature Deactivating: Occurs while a feature is deactivating
3) Feature Installation: Occurs when a feature has been installed
4) Feature Uninstalling: Occurs while a feature is un-installing
5) Feature Upgrading: Occurs while a feature is upgrading

Feature Receiver Event Classes

1) Microsoft.SharePoint.SPFeatureReceiver
To implement feature receivers, you need to define a new class that inherits from the base abstract class, SPFeatureReceiver, defined in the Microsoft.SharePoint namespace.
public abstract class SPFeatureReceiver {
public SPFeatureReceiver();
public virtual void FeatureActivated(SPFeatureReceiverProperties properties);
public virtual void FeatureDeactivating(SPFeatureReceiverProperties properties);
public virtual void FeatureInstalled(SPFeatureReceiverProperties properties);
public virtual void FeatureUninstalling(SPFeatureReceiverProperties properties);
public virtual void FeatureUpgrading(SPFeatureReceiverProperties properties,
string upgradeActionName, IDictionary<string, string> parameters);}

2) Microsoft.SharePoint.SPFeatureReceiverProperties
Each virtual method accepts an argument of type SPFeatureReceiverProperties, which allows accessing information about the target feature, its definition, and the current site.
public sealed class SPFeatureReceiverProperties : Idisposable {
public SPFeatureDefinition Definition { get; internal set; }
public SPFeature Feature { get; }
public SPSite UserCodeSite { get; }}

Feature.Parent property
We can access the context of the feature through the Feature.Parent property of the current SPFeatureReceiverProperties argument.
public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
{
  SPSite site = properties.Feature.Parent as SPSite; //Depending on the scope of your feature
}

Feature.Parent Scope
Depending on the scope of your feature, the Parent property could be:-
1) The whole farm (SPFarm),
2) A single web application (SPWebApplication),
3) A Site Collection (SPSite),
4) A single website (SPWeb).

Feature Receiver Reference
To create a feature receiver, you need to implement the receiver class, build its assembly, put it into the GAC, and declare the ReceiverAssembly and ReceiverClass attributes in a feature manifest XML file.

<Feature xmlns="http://schemas.microsoft.com/sharepoint/" Version="1.0.0.0"
Title="My Web Part"
Description="This feature deploys a sample Web Part."
Id="c46c270e-e722-4aa0-82ba-b66c8dd61f4e"
ReceiverAssembly="MyApp.SP2010.MyFeature, Version=1.0.0.0,
Culture=neutral, PublicKeyToken=b001133e0647953d"
ReceiverClass="MyApp.SP2010.MyFeature.MyWebPartEventReceiver"
Scope="Site">
    <ElementManifests>
        <ElementManifest Location="MyWebPart\Elements.xml" />
        <ElementFile Location="MyWebPart\MyWebPart.webpart" />
    </ElementManifests>
</Feature>

Adding a Feature Receiver
In Visual Studio 2010, go to the Solution Explorer and right-click a feature item within the Features folder of your SharePoint project to open the contextual menu. There, you can select the Add Event Receiver menu item, which will create all the plumbing code for you.



Hope this gives a brief overview about SharePoint 2010 Feature Receivers.  In the next post we will create a sample feature receiver in order to take a deeper look.

References
2) Microsoft SharePoint 2010 Developer Reference, by Paolo Pialorsi - Book








Monday, April 1, 2013

SharePoint 2010 - Upload and Install Setup files (.exe, .msi etc) from a Document Library

Overview
Recently I came across a scenario where an .msi file needed to be uploaded to a SharePoint 2010 document library. Also, on clicking the setup file, it should run directly instead of downloading the file. After a few modifications in the central admin, I was able to achieve this. Following are the steps:-

Objective
1) By default, SharePoint doesn't allow files like .exe or .msi to be uploaded in the document library. First of all we need to allow these files to be uploaded.
2) Secondly, whenever we click on a file in document library, by default it has only download option. We must have and addition "Run" option too.

So, lets get started.....

Enabling setup files (exe, msi etc) to be Uploaded to Document Library

Create a document library and try to upload an .msi file.

You will get the following error

To unblock such files, go to Central Admin->Security->Define blocked file types.

Choose the webapplication, select msi option and delete it. Click on OK button to save the settings.

Now go back to the library and try to upload the msi file. It will get uploaded.
But if click on this file you will get only the option for saving the file. We need the option to run it directly.



Enabling setup files (exe, msi etc) to Run from Document Library

Go to Central Admin->Application Management->Manage Web Applications. Choose the web application and select General Settings.

The following window will pop up. In the "Browser File Handling" section select "Permissive" option.

Now go back to the document library and click on the file. This time you will get a "Run" option.

When you click on Run, the installation will begin.

Of course, there is a reason why these functionalities are blocked by default. While making such changes, always make sure that there are no security loop holes.

Hope this post might be of some help to you!!