A new concept of remote event receivers have been introduced in SharePoint 2013. 

These are similar to event receivers in 2010 except that they run remotely and not actually on server.  Hence we user CSOM in the handlers.

There can be two type of event receivers

1. App event receivers (Handles events link appinstalled, appuninstalled etc)

2. Remote event receivers. (Can handle list or listitem events)

Now we need to be clear that app event receivers and Remote event receivers work in Cloud Hosted App i.e. auto hosted or provider hosted.  They do not work with SharePoint Hosted apps.  I have seen some examples on net having remote event receivers on SharePoint Hosted app but event receivers are not meant for SharePoint Hosted App.  There are some methods of these receivers to get client context and they dont work with SharePoint Hosted app.  I had a tough time struggling with an event receiver on SharePoint Hosted app and then I stumbled on a line in msdn

Excerpt from MSDN

Note

Remote event receivers and app event receivers work only with cloud apps for SharePoint (that is, provider-hosted apps). These receivers don't work with SharePoint-hosted apps for SharePoint.

Source - http://msdn.microsoft.com/en-us/library/office/jj220048(v=office.15).aspx

How Does it work

Web services are used in remote event receiver. 

When we add a remote event receiver to an app, a web service also gets added which handles these events.

Open Visual studio, Create a new project (App For SharePoint).  I am going to select AutoHosted.

Now Add New List.  Name the list “ListInApp”.

Now click add new item, Select Remote Event Receiver.  It would ask for list name to be associated with.  Select list just created ‘ListInApp’

image

Name it as AppListReceiver. 

Next select “List Item Event” in type of event receiver.  Select the list ListinApp that we just created. (Notice there are ItemAdding and ItemAdded, ItemDeleting and ItemDeleted and so forth)

image

I am going to select ItemDeleting and ItemAdded.

Notice AnnouncementReceiver.svc gets added in the solution explorer in the App Web project.

image

In the .svc file we notice there are 2 methods. ProcessEvent and ProcessOneWayEvent.

Now before we get into code let us look at the events

We can handle Before and After events.  Now the Before events i.e. ItemAdding, ItemDeleting, etc are always synchronous while the after events i.e. ItemAdded, ItemDeleted etc can be synchronous as well as asynchronous

ProcessEvent handles the synchronous methods while ProcessOneWayEvent are one way, i.e. asynchronous.  They just fired and are forgotten. 

Notice I selected ItemDeleting and ItemAdded.

I am going to handle ItemDeleting to stop allowing to delete any items from my list.

public SPRemoteEventResult ProcessEvent(SPRemoteEventProperties properties)
       {
           SPRemoteEventResult result = new SPRemoteEventResult();

           if (properties.EventType == SPRemoteEventType.ItemDeleting)
           {
               result.ErrorMessage = "Deleting items from this list is not allowed";
               result.Status = SPRemoteEventServiceStatus.CancelWithError;
           }

           return result;

}

 

Similarly we can write code in ItemAdded even in the method ProcessOneWayEvent

Getting ClientContext in Remote Event Receivers.

Now to get client context there is a method available TokenHelper.CreateRemoteEventReceiverClientContext(properties)

Now a point to note here is the client context we get here is that of app web.  That is because the event receiver is to handle events on a list on app web.  If the event receiver is written to handle events of list on host web, the context returned is that of host web.

This brings the question how do we create remote event receiver to a list of host web.  We do not get that option in Visual studio.  This has to be done programmatically.  Let us see how

Remote event receivers for list on host web

To do this I am going to write an app event receiver.  My plan is to code an app.  When this app gets installed, it add an event receiver to a list of host web. 

Create a new app project for sharepoint.  Select AutoHosted App. 

Go to properties of the app and select the property “HandleAppInstalled”  Set it to True

image

On doing so we will find AppEventReceiver.svc added to solution explorer in the appweb project

image

This would have method ProcessEvent

public SPRemoteEventResult ProcessEvent(SPRemoteEventProperties properties)

Further Below code can be self explanatory

public SPRemoteEventResult ProcessEvent(SPRemoteEventProperties properties)
       {
           SPRemoteEventResult result = new SPRemoteEventResult();

           switch (properties.EventType)
           {
               case SPRemoteEventType.AppInstalled: HandleAppInstalled(properties);
                   break;

                case SPRemoteEventType.AppUnInsstalled: HandleAppUninstalled(properties); break;
            }

           return result;

}

 

In HandleAppInstalled we will try to attach remote event receiver to host web’s list.  Now to do this we need client context to host web. 

SP gives us a magical method TokenHelper.CreateAppEventClientContext(properties,false)

If the second parameter of this method is false, it returns us the client context to host web else it returns us the client context to app web.

Note that this method is available only with App event receiver and when we try to use it with remote event receiver it returns null.

Below is the code

private void HandleAppInstalled(SPRemoteEventProperties properties)
      {

using (ClientContext clientContext =TokenHelper.CreateAppEventClientContext(properties,false))
          {
              if (clientContext != null)
              {
                  bool rerExists = false;
                  List myList = clientContext.Web.Lists.GetByTitle("MyAnnouncements");
                  clientContext.Load(myList, p => p.EventReceivers);
                  clientContext.ExecuteQuery();

                  foreach (var rer in myList.EventReceivers)
                  {
                      if (rer.ReceiverName == "ItemAddedEvent")
                      {
                          rerExists = true;
                      }
                  }

                  if (!rerExists)
                  {
                      EventReceiverDefinitionCreationInformation receiver = new EventReceiverDefinitionCreationInformation();
                      receiver.EventType = EventReceiverType.ItemAdded;
                      receiver.ReceiverName = "ItemAddedEvent";
                      OperationContext op = OperationContext.Current;
                      receiver.ReceiverUrl = op.RequestContext.RequestMessage.Headers.To.ToString();
                      receiver.Synchronization = EventReceiverSynchronization.Synchronous;
                      myList.EventReceivers.Add(receiver);
                      clientContext.ExecuteQuery();
                  }

} }  }

 

The above code attaches event receiver to the MyAnnouncements list of host web.  Now you must be wondering where do we write the event handler for this.  If you closely observe the code we have given the Receiver url of the same class, hence we can write the event handler here itself.

The process event function of AppEventReceiver.svc gets changed to this

public SPRemoteEventResult ProcessEvent(SPRemoteEventProperties properties)
       {
           SPRemoteEventResult result = new SPRemoteEventResult();

           switch (properties.EventType)
           {
               case SPRemoteEventType.AppInstalled: HandleAppInstalled(properties);
                   break;

                case SPRemoteEventType.AppUnInsstalled: HandleAppUninstalled(properties); break;

                case SPRemoteEventType.ItemAdded: HandleItemAdded(properties); break;
            }

           return result;

}

We add a function HandleItemAdded and that would have the code what needss to be done when we an item is added to MyAnnouncements list.

Debugging

Last but not the least, how do I debug this app?  To do this we can use Windows Azure service bus.

MSDN Link to How to debug remote events

Happy Coding!!!