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
- 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).
- One project for SharePoint App
-
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/.
-
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:
-
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.
- The Remote Event Receiver Elements.xml declaration looks like this :
-
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.
-
-
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.
-
-
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”;
//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.
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 ?
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.
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
Incase of existing list what you will do?
ClientContext clientContext = TokenHelper.CreateAppEventClientContext(properties, false)
always null
Yes, i’m also getting the Null value. Can anyone help on this?
hi Tester
sorry feels to me like long time ago ^^
I cant remember exactly but – I did get null value, when there was something wrong with clientID/secret in “visual studio projects” and cliendID/secret on “azure webApp” (azure web site its called today?)
(null when creating client context means that “whole” puzzles dont play together)
(hm maybe in these comments, search for “I used “url token” in app manifest. It is working with” and there I wrote about “www” adress issue) .. but i guess its clienID/secret issue 🙂
Thank You!!! Details I have been looking for! However, I did get lost on the Config step – Microsoft once again has changed the interface and I cannot find where to add the ClientID/Secret – help??
I have tried and tried and tried this over the past some 6 days. Nothing works. Thousands and thousands of searches have come up empty. I have started over with new projects, verified everything 3 times each to no avail. All I get when the App is loaded I get “something went wrong”. For the life of me I cannot understand why this is so touchy. I could have built 1000 Event Receivers using any other method.
Doesn’t anyone have a simple event handler that WORKS? This is more than painful. Right now I’d gladly pay someone for a working example.
Can you help on the steps you accomplished , been dealing with this headache for a week now
Hello all
I can confirm on 12 July 2017 hostweb listItemAdding/Added Remote Event Receiver on sharepoint online / azure app service __is working.
My issuses were:
(I had not DNS … i was using wrong domain name in /_layouts/15/AppRegNew.aspx (I was using www. instead of “without www.” in front)
I used “url token” in app manifest. It is working with:
https://test123456789test.azurewebsites.net/AppEventReceiver.svc
https://test123456789test.azurewebsites.net/AppEventReceiver.svc
Azure app service without domain is /_layouts/15/AppRegNew.aspx domain “without www.” just “site789.azureetc.net”.
Another step. I too added into azure app service / application settings parameters ClientId and ClientSecret.
Sorry im not so clear, but RER on hostweb is working (but it was hard to make it working ^^)
i get the following error: first on publishing the web app ,
it tells me:You do not have permission to view this directory or page.
Second the addin doesn’t installed,error: cannot connect to remote event receiver
Is it possible to get the code you used or even the steps taken, i just cant seem to be able to make it work. Your help will be very much appreciated.
Hi keshav
I just google error about publishing web app:
https://support.microsoft.com/en-hk/help/942044/error-message-when-you-try-to-run-a-web-application-that-is-hosted-on
(I created azure “web server” (hosting website, dont know the name exactly”) from my Microsoft account .. I didnt make any changes to Web.config)
From I remember, in visual studio, on the left (server explorer?) I was able to see all “web sites” from Azure .. I just click right and publish (something like that)
similar like https://www.youtube.com/watch?v=0E0xjpVaEHY
(this is just opinion: because you dont have permission from your account in visual studio to azure webSite –
it seems when you deploy sharepoint addin into sharepoint, because “sharepoint online” want to connect to your (maybe) azure web site, but that directory is empty (because files were not publish)
summary: I would try to correct publish files into azure website. After this step is done successfully, take step to deploy sharepoint addin 🙂
Great article! Works like a charm without any issues. Should follow all the steps as explained otherwise things won’t work.
Hello,
In detail explanation, Thanks. While creating App identifier client ID and client secret using appregnew.aspx, do we need to generate it from App web? (I mean root site of the tenant). Also, if we need to use list events like list was added, do we need to add the event receiver to the host web? please guide.