There are a number of articles talking about how to deploy Remote Event Receiver for SharePoint 2013, but few of them are in depth, especially on how to set it up for host web using Provider Hosted App in Office 365/SharePoint Online environment. I hope this post can provide detailed information for developers who need to deploy the same.

The inspiration for this article is another similar article written by Chris O’Brien, here. However the mentioned article talks about how to make the BasicDataOperations SP2013 provider-hosted app on MSDN work on App Web, not Host Web. Most of the steps in terms of hosting the app are identical (except the screen grabs from the updated Windows Azure Management Portal). Deploying Remote Event Receiver also works better with Provider Hosted App instead of Auto Hosted App as the former provides much better control on how and where to deploy the remote event code.

This article deploys a Remote Event Receiver that gets attached to an existing custom list on host web of Office 365/SharePoint online environment. The remote event receiver fires on ItemAdded event of the custom list on host web. The name of the existing list on host web is “Feedback”. In this example, moment an item is added to the Feedback list another new item gets created and it continues in an infinite loop as the RER gets activated on ItemAdded event. This is just an example and in real life, a lot of different business requirements can be accomplished using RER. One good example is probably remote site provisioning. You can download the zipped code end of the post. In order to stop the creation of items infinitely in the list, you can uninstall the app from the host web which will detach the event receiver from the host web list.

The step-by-step guide

  1. Obtain the BasicDataOperations SP2013 provider-hosted app on MSDN. It is recommended to use this solution for the first timers, to get the code and Remote Event Receiver declaration right. This solution has got two projects :
    • One project for SharePoint App
    • One for the remote component ( ASP.Net website that hosts the WCF service for Remote Event Receiver).
  2. Create an Azure website in the Azure Management Portal. Make sure to note the URL of the website. In my case it is https://anindyadev.azurewebsites.net/.


  3. Login to your Office 365/SharePoint tenant and navigate to the app registration page ( https://<servername>/_layouts/15/appregnew.aspx ) of the site which is the Host Web in this context. Generate the Client Id and Client Secret by clicking the Generate buttons.



    Then click on Create button. You can see the next screen something similar to the one shown below:


  4. Update the SharePoint App project so that the URL references point to the Azure website.
    • The Remote Event Receiver Elements.xml declaration looks like this :
    <?xml version=1.0” encoding=utf-8?>
    <Elements xmlns=http://schemas.microsoft.com/sharepoint/>
    <Receivers ListTemplateId=100>
    <Receiver>
    <Name>RemoteEventReceiver1ItemAdded</Name>
    <Type>ItemAdded</Type>
    <SequenceNumber>15000</SequenceNumber>
    <Url>https://anindyadev.azurewebsites.net/RemoteEventReceiver1.svc</Url>
    </Receiver>
    </Receivers>
    </Elements>
    • The AppManifest.xml declaration looks like this :
    <?xml version=1.0” encoding=utf-8 ?>
    <!–Created:cb85b80c-f585-40ff-8bfc-12ff4d0e34a9–>
    <App xmlns=http://schemas.microsoft.com/sharepoint/2012/app/manifest” Name=BasicDataOperations” ProductID={13823eb3-b415-4c21-9884-e67182aa12ce}” Version=1.0.0.0” SharePointMinVersion=15.0.0.0>
    <Properties>
       <Title>BasicDataOperations</Title>
       <StartPage>https://anindyadev.azurewebsites.net/Pages/Default.aspx?{StandardTokens}</StartPage>
       <InstalledEventEndpoint>https://anindyadev.azurewebsites.net/AppEventReceiver.svc</InstalledEventEndpoint>
       <UninstallingEventEndpoint>https://anindyadev.azurewebsites.net/AppEventReceiver.svc</UninstallingEventEndpoint>
    </Properties>
    <AppPrincipal>
       <RemoteWebApplication ClientId=29c3e27a-0611-4c04-aa14-407e4adc813d/>
    </AppPrincipal>
    <AppPermissionRequests AllowAppOnlyPolicy=false>
       <AppPermissionRequest Scope=http://sharepoint/content/sitecollection/web” Right=FullControl />
    </AppPermissionRequests>
    </App>

    The ClientId should match the ClientId in step 3. Also note that I have got an element for UninstallingEventEndpoint as I am removing the remote event receiver from the custom list on host web, when the App gets uninstalled. In terms of AppPermissionRequest, Manage right should be good enough to handle list items. In my example I have used FullControl.

  5. Publish the ASP.Net website (hosting the WCF service for the Remote Event Receiver) to Azure. Web Deploy process has been used to publish the website.
    • Go to your Azure management portal. Click on ‘WEB SITES’ on your left hand site. This shows the list of sites you created. Click on the NAME of the associated site, created for this purpose (in my case it is https://anindyadev.azurewebsites.net/)


    • Download the Publish Profile for your Azure website. Save it locally on your disk. In my case the name of the downloaded profile is anindyadev.azurewebsites.net.PublishSettings .


    • Right click on the ASP.Net website project in Visual Studio and select Publish, since this is the first time.


    • The Publish Web dialog opens up. Import the publish profile downloaded previously.


    • The following screens appear one after another when you hit Next.




    • Click Publish to deploy your Azure website. You should see a success message.


      Now the remote event receiver is deployed on Azure website.

  6. As AppSettings are not pulled from the app’s web.config file in Azure Websites, we need to configure them actually in Azure. 
    • Go to your Azure management portal. Click on ‘WEB SITES’ on your left hand site. This shows the list of sites you created. Click on the NAME of the associated site, created for this purpose (in my case it is https://anindyadev.azurewebsites.net/)
    • Click on CONFIGURE.


    • Once on the configuration page, scroll down to the app settings section. Enter the ClientId and ClientSecret here and Click Save.


  7. Now publish the SharePoint App to Office 365/SharePoint Online( first by publishing to the local file system )
    • Right click on the SharePoint App project and click on Publish.


    • Select the publishing profile created in step 5 and click Next.


    • Enter the ClientId and ClientSecret in the next screen, as obtained in step 3. Click Next.


    • Click Finish on the next screen.


    • Finally the app gets published on the local file system


    • You can now add the BasicDataOperations.app to the App Catalog of your Office 365/SharePoint Online tenant.


    • After this, the app can be added on your Host Web. When prompted for permission, click on Trust it.


      The app gets installed on host web.

      Now if you go to the Feedback list and add an item, you can see infinite items getting created with the title ‘TITLE CHANGED BY RER’ in the list.


      I added the item with title ‘Hello’ and all other items were getting created by RER with the title ‘TITLE CHANGED BY RER’.

The Code Base

There are two main classes to be paid attention to.

  • First one is AppEventReceiver.cs which handles the app installed/uninstalling event. After the app gets installed, it attaches the Remote Event Receiver with the Feedback list. During the uninstalling event, it deletes the Remote Event Receiver from the list.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.Text;
using Microsoft.SharePoint.Client;
using Microsoft.SharePoint.Client.EventReceivers;

namespace BasicDataOperationsWeb
{
  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 Feedback
                   var documentsList = clientContext.Web.Lists.GetByTitle(“Feedback”);
                   clientContext.Load(documentsList);
                   clientContext.ExecuteQuery();
                   string remoteUrl = https://anindyadev.azurewebsites.net/RemoteEventReceiver1.svc&#8221;;

                   //Create the remote event receiver definition
                   EventReceiverDefinitionCreationInformation newEventReceiver = new EventReceiverDefinitionCreationInformation()
                   {
                     EventType = EventReceiverType.ItemAdded,
                     ReceiverAssembly = Assembly.GetExecutingAssembly().FullName,
                     ReceiverName = “RemoteEventReceiver1”,
                     ReceiverClass = “RemoteEventReceiver1”,
                     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(“Feedback”);
              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 == “RemoteEventReceiver1”)
                   {
                        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;

   }

   publicvoid ProcessOneWayEvent(SPRemoteEventProperties properties)
   {
     // This method is not used by app events.

      }

  }
}

Please note the way I created the ClientContext. The value of false in the second parameter tells the AppEventReceiver to create the context in terms of Host Web, but not App Web.

  • The second class is the Remote Event Receiver itself – RemoteEventReceiver1.cs. 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.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using Microsoft.SharePoint.Client;
using Microsoft.SharePoint.Client.EventReceivers;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Channels;
using Microsoft.SharePoint.Client.Social;

namespace BasicDataOperationsWeb
{
 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(“Feedback”);
                    ListItemCreationInformation itemCreateInfo = newListItemCreationInformation();
                    ListItem oListItem = imageLibrary.AddItem(itemCreateInfo);
                    oListItem[“Title”] = “TITLE CHANGED BY RER”;
                    oListItem.Update();
                    clientContext.ExecuteQuery();
               }
               catch (Exception ex){ }
          }
      }
     }
  }

 }

}

Please note the way I am creating the ClientContext.

Here is the link to the sample code.

Category:
SharePoint

Join the conversation! 7 Comments

  1. Wonderful post Anindya.Very detailed .Made things so clear to me .
    Had a quick question : you mentioned :’In order to stop the creation of items infinitely in the list, you can uninstall the app from the host web which will detach the event receiver from the host web list’.
    Is there a programmatic way to do it?(say) after the creation of the 51st item ?

    Reply
    • Hi Sujoy :

      Yes you should be able to. Just before creating an item in the Remote Event Receiver, you can get all the items from the list and then do something like below:

      var count = imageLibrary.items.count;

      if( count < 51 ){

      //write the code for item creation

      }

      That's all.

      Reply
  2. I tried the same code in SharePoint online and azure account the event receiver was not triggered. Do i need to activate any services

    Thanks,
    Krishna K.V

    Reply
  3. […] Remote Event Receiver (RER) for Host Web … – Remote Event Receiver (RER) for Host Web using SharePoint Provider Hosted App in Office 365/SharePoint Online Environment […]

    Reply
  4. Incase of existing list what you will do?

    Reply
  5. ClientContext clientContext = TokenHelper.CreateAppEventClientContext(properties, false)

    always null

    Reply

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: