Sunday, 26 January 2014

Add/delete and list Remote Event Receivers with PowerShell/CSOM

Recently I’ve been looking at Remote Event Receivers more and more, as I think they are important (and somewhat unavoidable) if you are trying to build “cloud-friendly” SharePoint solutions – either because you’re on Office 365, or simply want to leave the door open for such a move. You might need to use a RER for something in the host web or app web. I’ll most likely write more on RERs in the future, but if you need a basic step-by-step guide to Remote Event Receivers, my previous post Deploying SP2013 provider-hosted apps/Remote Event Receivers to Azure Websites (for Office 365 apps) may be useful. In this post I want to share some potentially useful PowerShell (and background info), for those who work with RERs.

As I note in the article at the previous link, when you create an RER you actually need to create an app for SharePoint, even if it is an RER to be used in the host web. The app must be either provider-hosted or auto-hosted. For production use I like the provider-hosted option, even if the code is deployed to a cloud service such as Azure. This offers much more flexibility than auto-hosted, which doesn’t have the same options for configuration/monitoring/scaling-up etc. An app is needed because you are creating remote code which most likely needs to use OAuth to communicate back to SharePoint, and the trust model means that (in the standard case at least) an administrator such as the site owner needs to agree to the permissions requested by the app. This could be “Web – Read” or “Site Collection – FullControl” and so on.

Registering Remote Event Receivers

There are several ways to register RERs:

  • Declaratively
  • With CSOM code e.g. in the AppInstalled event
  • With a PowerShell/CSOM script

One big downside to the declarative approach is that it can only be used for lists in an app web (i.e. a SharePoint list deployed by the app). It cannot be used for lists in the host web (e.g. to add a RER to a list in a team site). For completeness, the declarative XML is shown below – it’s just like the XML you might have used for any other event receiver, the only difference is the new “Url” element in the XML:

** N.B. There is a code sample here but it will not show in RSS Readers - click here for full article **

I’ve found more and more that as I’m doing development, the PowerShell approach is highly useful. Sometimes you just need to directly interact with the list - perhaps to see if your RER really is registered properly, or change the URL to a different WCF service for testing. Since there is no user interface for setting RERs, some quick PowerShell is ideal – this post is to share my functions in case they’re useful. I’ll list the different ones for adding/deleting/listing RERs, then provide a full/combined script at the end.

By the way, if you’re new to the idea of PowerShell scripts which have CSOM code embedded in them, see Using CSOM in PowerShell scripts with Office 365.

Adding a new Remote Event Receiver

The function below adds a remote event receiver to a named SharePoint list.

(N.B. Note that all the functions below require a valid ClientContext object to be passed in – see the Prerequisites section towards the end of this post for more details.)

** N.B. There is a code sample here but it will not show in RSS Readers - click here for full article **

Delete a Remote Event Receiver

The function below removes a remote event receiver from a named SharePoint list.

** N.B. There is a code sample here but it will not show in RSS Readers - click here for full article **

List Remote Event Receivers on a SharePoint list

In fact, RER declarations are just like regular event receivers – the SPList class just has one “EventReceivers” property, rather than separate collections for remote event receivers and regular event receivers:

** N.B. There is a code sample here but it will not show in RSS Readers - click here for full article **

Combined/all-up script

So having walked through the functions individually, here's a combined script for download/copy and paste:

** N.B. There is a code sample here but it will not show in RSS Readers - click here for full article **

Prerequisites

To get started with these scripts you should follow the “Getting Started” section of Using CSOM in PowerShell scripts with Office 365, including the “The top of your script – referencing DLLs and authentication” section.

All of the samples above need you to pass a valid ClientContext object – which you have once you have provided the credentials and URL, and have authenticated to SharePoint/Office 365. As in my previous posts, I obtain this in a separate file which I call something like TopOfScript_PSCSOM.ps1. For clarity, here’s an idea of what you need:

** N.B. There is a code sample here but it will not show in RSS Readers - click here for full article **

Summary

Hopefully this script is useful to those working with RERs. Using PowerShell/CSOM isn’t the only way to declare a Remote Event Receiver – in production you might use CSOM code in the AppInstalled event (which is itself declared declaratively in AppManifest.xml – the only way for that event), but the PowerShell/CSOM approach is definitely useful in dev. Happy coding!

12 comments:

Marius Ene said...

I am confronting with the following situation: I have an RER(remote event receiver) on a document library, which fires on update. In some situations this RER is actually updating some metadatas on the document.

To avoid the looping (since there is now EventFiringEnabled for RER) I've tried to remove the RER, do the update and added back.

Didn't work, so I had to come up with a workaround (flags, not at all pretty).

Do you know of better way to overcome this issue?

Thanks

Anonymous said...

Chris,

This works great for remote hosted RERs. Is there a way we could modify these scripts to work with an auto-hosted RER? It seems like the answer would be no since you don't know the endpoint of the RER in an auto-hosted app until the app is installed. Thoughts?

aschattopadhyay said...

Hi Chris :

I have followed your article on how to attach RER on a provider hosted app : http://www.sharepointnutsandbolts.com/2013/07/deploying-sp2013-provider-hosted.html.

It works perfectly with my custom list or any other OOB list e.g. Documents. However moment I attach it to MicroFeed list, it doesn't work. I can see the RER is attached. However nothing happens. My event is ItemAdded.

Is that a known issue with MicroFeed list?

Cheers!

Chris O'Brien said...

Hi guys,

Thanks for the comments. My thoughts on those questions:

- @Marcus - no, I'm not aware of any alternatives. But then again I've not played with DisableEventFiring in the context of RERs. Are you saying that doesn't help?
- @Eric - no, this wouldn't be possible for the reason you describe: it's a URL which changes on each app installation. So, you can only use the declarative approach and the ~remoteAppUrl token - and that only works in the app web
- @aschattopadhyay - hmm, I'm not aware of any differences with the MicroFeed list, but in general I'd try to avoid solutions where you are hooking a RER onto a system list like this. I could definitely believe that's not supported (but don't have definitive info).

Cheers,

Chris.

aschattopadhyay said...

Hi Chris :

I just wanted to point out the RER doesn't work with MicroFeed list. Somehow Microsoft disabled the ItemAdded event probably. Even if I have a SharePoint Designer Workflow against the list on item created event, it doesn't fire.

We finally ended up doing the same functionality by deploying SharePoint CSOM code on Azure worker role.

Thanks.

Kelvin Hu said...

Hi Chris,

Really thanks for your great article, now I can setup Remote Event Receivers to receive events of changes on host web.

But there is only one thing: the "X-SP-ContextToken" header in HTTP request sent to my RER is blank, I think it is needed for my RER to access SharePoint resource. Do you have any ideas?

Thanks

Chris O'Brien said...

@Kelvin,

Yes! I also see the same behaviour - I have been investigating this for a *long* time. I currently have a Service Request open with Microsoft to look at this.

Sorry I don't have a better answer right now, but I'll be blogging about this very soon. Out of interest, are you working in Office 365 or on-premises SharePoint?

Thanks,

Chris.

Kelvin Hu said...

Hi Chris,

Thanks for your quick reply, and also thanks for your confirmation. BTW, I am using Office 365.

Looking forward to your update.

Thanks

Chris O'Brien said...

@All,

** UPDATE WHICH MAY BE USEFUL TO ANYONE HITTING THIS POST BECAUSE THEIR CODE DOES NOT GET CLIENTCONTEXT IN THE REMOTE EVENT RECEIVER:

The issue is that RERs on the host web must obtain their ClientContext in a specific way. Things will work if you get an "app only" context, using TokenHelper.GetAppOnlyAccessToken() as the starting point.

It does NOT appear to be possible to get an "app + user" context in remote event receivers currently - this is the issue I mention above. But the workaround above helps in most scenarios.

Thanks to Kirk Evans for helping me identify this!

Cheers,

Chris.

**

daniel said...

hi Chris,

is there a way to load all of the ListAdded rer in a site?

Chris O'Brien said...

@Daniel,

Do you mean all of the event receivers for the ListAdded event which are remote (RERs)? If so, yes - you should be able to get this from the microsoft.sharepoint.client.web.eventreceivers property. Just loop through the items, and if one has a value for the ReceiverUrl property, it's an RER.

HTH,

Chris.

Anonymous said...

I have followed this guide to attach my ItemDeleting Remote Event Receiver but preventing adding an item via the ItemDeleting doesn't work in the host web, even though it fires and I return a result.Status = CancelWithError.

Any ideas?