I want to develop and debug a sharepoint remote event receiver. I am using the Ngrok for debugging our RER, but i am facing some problems, which did not happen when i were using the azure service bus for debugging.
Here is a full description about my case:-
1) Inside our sharepoint online i created a new developer site collection.
2) Using Visual Studio pro 2015 >> i created a new Visual Studio project of type SP Add-in.
3) I selected the Type = Provider-hosted, as follow:-
4) After that i changed the Handle Add-in installed/uninstalled to True:-
5) Then i open the Ngrok command line, i enter the following:-
ngrok http --host-header=rewrite 50452// where this port is our RER port inside visual studio
Where 50452 is the port for the VS project:-
I got the following inside the Ngrok command link:-
So i updated the AppManifest.xml with the forwarding url:-
6) I update the app permission as follow:-
7) Then i run the project >> i got this popup >> i select the custom list named "projects":-
Where i got to the break-point inside my code >> but the clientContent inside my code will be null:-
9) After that the VS stop running and i got this error:-
Here is the full code inside my "AppEventReceiver.svc"
public class AppEventReceiver : IRemoteEventService { private const string ReceiverName = "ItemAddedEvent"; private const string ListName = "projects"; /// <summary> /// Handles app events that occur after the app is installed or upgraded, or when app is being uninstalled. /// </summary> /// <param name="properties">Holds information about the app event.</param> /// <returns>Holds information returned from the app event.</returns> public SPRemoteEventResult ProcessEvent(SPRemoteEventProperties properties) { SPRemoteEventResult result = new SPRemoteEventResult(); switch (properties.EventType) { case SPRemoteEventType.AppInstalled: HandleAppInstalled(properties); break; case SPRemoteEventType.AppUninstalling: HandleAppUninstalling(properties); break; case SPRemoteEventType.ItemAdded: HandleItemAdded(properties); break; } return result; } private void HandleAppUninstalling(SPRemoteEventProperties properties) { using (ClientContext clientContext = TokenHelper.CreateAppEventClientContext(properties, false)) { if (clientContext != null) { List myList = clientContext.Web.Lists.GetByTitle(ListName); clientContext.Load(myList, p => p.EventReceivers); clientContext.ExecuteQuery(); var rer = myList.EventReceivers.Where( e => e.ReceiverName == ReceiverName).FirstOrDefault(); try { System.Diagnostics.Trace.WriteLine("Removing ItemAdded receiver at " + rer.ReceiverUrl); //This will fail when deploying via F5, but works //when deployed to production rer.DeleteObject(); clientContext.ExecuteQuery(); } catch (Exception oops) { System.Diagnostics.Trace.WriteLine(oops.Message); } } } } private void HandleAppInstalled(SPRemoteEventProperties properties) { using (ClientContext clientContext = TokenHelper.CreateAppEventClientContext(properties, false)) { if (clientContext != null) { List myList = clientContext.Web.Lists.GetByTitle(ListName); clientContext.Load(myList, p => p.EventReceivers); clientContext.ExecuteQuery(); bool rerExists = false; foreach (var rer in myList.EventReceivers) { if (rer.ReceiverName == ReceiverName) { rerExists = true; System.Diagnostics.Trace.WriteLine("Found existing ItemAdded receiver at " + rer.ReceiverUrl); } } if (!rerExists) { EventReceiverDefinitionCreationInformation receiver = new EventReceiverDefinitionCreationInformation(); receiver.EventType = EventReceiverType.ItemAdded; //Get WCF URL where this message was handled OperationContext op = OperationContext.Current; Message msg = op.RequestContext.RequestMessage; receiver.ReceiverUrl = msg.Headers.To.ToString(); receiver.ReceiverName = ReceiverName; receiver.Synchronization = EventReceiverSynchronization.Synchronous; myList.EventReceivers.Add(receiver); clientContext.ExecuteQuery(); System.Diagnostics.Trace.WriteLine("Added ItemAdded receiver at " + msg.Headers.To.ToString()); } } } } private void HandleItemAdded(SPRemoteEventProperties properties) { using (ClientContext clientContext = TokenHelper.CreateRemoteEventReceiverClientContext(properties)) { if (clientContext != null) { try { List photos = clientContext.Web.Lists.GetById( properties.ItemEventProperties.ListId); ListItem item = photos.GetItemById( properties.ItemEventProperties.ListItemId); clientContext.Load(item); clientContext.ExecuteQuery(); item["Title"] += "\nUpdated by RER " + System.DateTime.Now.ToLongTimeString(); item.Update(); clientContext.ExecuteQuery(); } catch (Exception oops) { System.Diagnostics.Trace.WriteLine(oops.Message); } } } } /// <summary> /// This method is a required placeholder, but is not used by app events. /// </summary> /// <param name="properties">Unused.</param> public void ProcessOneWayEvent(SPRemoteEventProperties properties) { throw new NotImplementedException(); } }
Question-1. So can anyone advice why i am getting Null for the ClientContext ? and why the project will stop running?
10) I also added a break-point inside the TokenHelper.cs, and the properties inside the return CreateAcsClientContextForUrl(properties, sharepointUrl); will have the following error:-
The endpoint address 'http://6ad2ebe4.ngrok.io/Services/AppEventReceiver.svc' does not match the app's endpoint 'localhost:44327'.
Question-2. Also i am not sure why i am getting that the port will be 44327 inside the above error, although in my case the VS project have a port = 50452 as shown in the above picture?? and i used the 50452 port inside the Ngrok command line ngrok http --host-header=rewrite 50452
Can anyone advice on my above 2 questions?
Thanks