Saturday 17 October 2015

All About Remote Event Receivers

Event receivers in earlier versions of SharePoint primarily ran on the SharePoint Server to handle events that occurred on SharePoint objects such as list, libraries, site etc.

In SharePoint 2013, a new concept, Remote Event Receivers, has been introduced, where the event generated by a SharePoint app could be listened to and handled by the SharePoint Server.

In other words, we could create SharePoint Apps (that is a standalone module of code that is complete in itself and can be installed / uninstalled independently on a Client) that can act as event generators. The handlers can be written using web services. These are very similar to the event receivers in the earlier version - except that these work in remote clients. This provides substantially more scope for including useful functionality in our SharePoint Apps. 
Remote event receivers are done by means of Web services, that listen for events to occur. Instead of running code on the SP server, the app fires an event that is handled by this web service. By registering a remote end-point we can invoke either a one-way or two-way event receiver. Visual Studio 2013 provides templates to create a Remote Event Receiver, that creates the skeleton for this set up, that we can build on, to meet our requirements. By default, when we use Visual Studio 2013 to create the remote event receiver, there are 2 methods in the WCF service; they are:
  1. ProcessEvent() that handles events that occur before an action occurs, such as when a user adds or deletes a list item. This is a synchronous event (2-way that can handle "-ing" (current) events) that can call-back to SharePoint, for example cancelling an addition to a list
  2. ProcessOneWayEvent() that handles events that occur after an action occurs, such as after a user adds an item to a list or deletes an item from a list. This is an asynchronous event (1-way that can handle "-ed" (past) events, fire and forget type)
Remote event receivers handles events in an item in the app such as list item, library item or web. In remote event receivers, app responds, when ever item added, updated or deleted in a list/library. When ever creating new remote event receiver you can select the type of event receiver. for Eg. you select ListItemEvent, that fires whenever user add/updates/deletes the list item.

 How Remote Events Works?
Remote event receivers follow the typical three patterns for authentication that are used for Auto hosted and SharePoint-hosted Apps for SharePoint: on-premises only, in the cloud only, and hybrid where part is on-premises and part is in the cloud. Remote event receivers only need to be concerned about authentication if they need to call back into SharePoint to perform some action on SharePoint. If your remote event receiver is of the fire-and-forget model, or if you are simply performing a validation and optionally cancelling an event, you do not need to be concerned with authentication in your code, but the manifest does need to have the correct designation. Figure 1 shows the on-premises-only and cloud-only configurations as well as the appropriate authentication used by the remote event receiver if your code needs to call back into SharePoint.

FIGURE 1:



Some enterprises that have their SharePoint site on-premises will choose to be configured for a hybrid environment where their remote event receivers may reside either on internal servers or in the cloud. In this case the enterprise might want a single authentication method and programming model for its remote event receivers that will work equally well regardless of where the remote event receiver is hosted. To accommodate this, the enterprise must follow the Microsoft-provided guidance to configure SharePoint to use Windows Azure Access Control Services (ACS) as the authorization service and expose the appropriate endpoints for SharePoint and any internally hosted remote event receivers to the public Internet. ACS must be able to access these endpoints to provide the needed authentication via OAuth. Figure 2 shows this hybrid pattern.
FIGURE 2


Although you have the opportunity to call back into SharePoint to do additional work within the app web, host web, or elsewhere depending on your app’s permissions, sometimes you might simply want to make some alterations on the list item and its properties that are currently being processed in the ProcessEvent method. You can do this by evaluating any value passed in on the properties object and then use the SPRemoteEventResult object and its ChangedItemProperties object to pass your alterations back to SharePoint.
For instance, you can use the properties.ItemEventProperties.AfterProperties object in your validation logic to assess whether the incoming values are as you expected them to be. Once you make any changes to your result object this will be passed back to SharePoint. SharePoint will update the list columns accordingly.

The following Try It Out walks you through using the SPRemoteEventResult object. Additionally, you will see in this example that because your app does not explicitly need to call back into SharePoint to read/write data, there is no need to use the TokenHelper class in your code.

Below are the The Code Base examples of  two methods:

ProcessEvent method:
which handles the app installed/uninstalling event. 
After the app gets installed, it attaches the Remote Event Receiver with the Product list. During the uninstalling event, it deletes the Remote Event Receiver from the list


public class AppEventReceiver : IRemoteEventService
  {
     public SPRemoteEventResult ProcessEvent(SPRemoteEventProperties properties)
     {
        SPRemoteEventResult 
result = new SPRemoteEventResult();
        if
 (properties.EventType == SPRemoteEventType.AppInstalled)
        {
           using
 (ClientContext clientContext = TokenHelper.CreateAppEventClientContext(properties, false))
           {
               if
 (clientContext != null)
               {
                   //Get reference to the host web list with name Products
                   var
 documentsList = clientContext.Web.Lists.GetByTitle(“Products”);
                   clientContext.Load(documentsList);
                   clientContext.ExecuteQuery();
                   string
 remoteUrl = https://ur  cloud host web url;
                   //Create the remote event receiver definition
                   EventReceiverDefinitionCreationInformation
 newEventReceiver =new EventReceiverDefinitionCreationInformation()
                   {
                     EventType = 
EventReceiverType.ItemAdded,
                     ReceiverAssembly = 
Assembly.GetExecutingAssembly().FullName,
                     ReceiverName = 
“ProductRemoteEventReceiver”,
                     ReceiverClass = 
“ProductRemoteEventReceiver”,
                     ReceiverUrl = remoteUrl,
                     SequenceNumber = 15000
                   };
                   //Add the remote event receiver to the host web list
                   documentsList.EventReceivers.Add(newEventReceiver);
                   clientContext.ExecuteQuery();
               }
           }
        }
        else 
if (properties.EventType == SPRemoteEventType.AppUninstalling)
        {
          using
 (ClientContext clientContext = TokenHelper.CreateAppEventClientContext(properties, false))
          {
              var
 list = clientContext.Web.Lists.GetByTitle(“Products”);
              clientContext.Load(list);
              clientContext.ExecuteQuery();
              EventReceiverDefinitionCollection
 erdc = list.EventReceivers;
              clientContext.Load(erdc);
              clientContext.ExecuteQuery();
              List
<EventReceiverDefinition> toDelete = newList<EventReceiverDefinition>();
              
foreach (EventReceiverDefinition erd in erdc)
              {
                   if
 (erd.ReceiverName == “ProductRemoteEventReceiver”)
                   {
                        toDelete.Add(erd);
                   }
              }
              //Delete the remote event receiver from the list, when the app gets uninstalled

              foreach
 (EventReceiverDefinition item in toDelete)
              {
                item.DeleteObject();
                clientContext.ExecuteQuery();
              }
          }
        }
     return result;
   }
  }
}


ProcessOneWayEvent method:
ProcessEvent  is a synchronous event handler and is used to call code when a “before” event occurs . ProcessOneWayEvent is an asynchronous event handler and is used to call code when an “after” event occurs . My code exists in ProcessOneWayEvent method as I am handling ItemAdded event here.
publicclassRemoteEventReceiver1 : IRemoteEventService
 {
  publicSPRemoteEventResult ProcessEvent(SPRemoteEventProperties properties)
  {
  SPRemoteEventResult result = newSPRemoteEventResult();
   using (ClientContext clientContext = TokenHelper.CreateRemoteEventReceiverClientContext(properties))
   {
     if (clientContext != null)
     {
          clientContext.Load(clientContext.Web);
          clientContext.ExecuteQuery();
     }
   }
   return result;
  }
  publicvoid ProcessOneWayEvent(SPRemoteEventProperties properties)
  {
     // On Item Added event, the list item creation executes
     if(properties.EventType == SPRemoteEventType.ItemAdded){
      using (ClientContext clientContext = TokenHelper.CreateRemoteEventReceiverClientContext(properties))
      {
          if (clientContext != null)
          {
               try
               {
                    clientContext.Load(clientContext.Web);
                    clientContext.ExecuteQuery();
                    List imageLibrary clientContext.Web.Lists.GetByTitle(“Products”);
                    ListItemCreationInformation itemCreateInfo = newListItemCreationInformation();
                    ListItem oListItem = imageLibrary.AddItem(itemCreateInfo);
                    oListItem[“Title”] = “TITLE CHANGED BY RER”;
                    oListItem.Update();
                    clientContext.ExecuteQuery();
               }
               catch (Exception ex){ }
          }
      }
     }
  }
 }
}

How It Works:

The SPRemoteEventResult object that is returned to SharePoint. SharePoint honors any modification you made to the object and updates the document list columns appropriately. It’s important to note that although you must choose Trust It when your app is installed, when using the SPRemoteEventResult object only, if your code is not explicitly calling back into SharePoint using CSOM or REST to read/write data, then you do not need to write code that uses the TokenHelper class. This example shows the pattern where your remote event receiver can impact data being written to SharePoint by modifying the SPRemoteEventResult object directly.
Hope this post was helpful! Millions of thanks for reading this blog.....happy sharepoint....happy coding...