Reasons to [Still] Love SharePoint’s SOAP Web Services

3 minute read

There are still reasons to love the SOAP Web Services (hopefully using SPServices!) even though they have been deprecated by Microsoft in SharePoint 2013 (and one can assume to upcoming SharePoint 2016) and SharePoint Online.

There are times when the REST API just doesn’t provide functionality we need, and the SOAP Web Services are a useful fallback when that’s the case.

I’ve run into two very specific instances where this was the case lately. Since Microsoft is actively trying to get REST up to snuff, I’ve added requests to the SharePoint User Voice for both of these. If you would like to see these fixed, please go to the User Voice links and vote them up. While we’re waiting, though, it’s SOAP to save the day.

Recurring Calendar Events

It’s extremely common to have recurring events in a SharePoint Calendar list. Usually this type of event is used for a recurring meeting, or it could just be a placeholder to remind a team to check something, etc.

If you’re building client-side functionality, you may want to do something like retrieving all of the occurrences of events to show in a widget like fullcalendar. Unfortunately, the REST API doesn’t know from recurrence.

There’s a sample at the OfficeDev/PnP repo, but if you run through it, you’ll see it’s pretty ugly. Ingenious, but ugly.

You can pass a CAML fragment into your REST call to augment the OData request, and here’s a different example of how that can work:

// Example from
  url: _spPageContextInfo.webAbsoluteUrl + "/_api/web/lists/getbytitle('Tasks')/GetItems(query=@v1)?@v1={\"ViewXml\":\"<View><Query><Where><And><Neq><FieldRef Name='Status' /><Value Type='Choice'>Completed</Value></Neq><Membership Type='SPWeb.Groups'><FieldRef Name='AssignedTo' /></Membership></And></Where></Query></View>\"}", 
  type: "POST", 
  headers: { 
      "X-RequestDigest": $("#__REQUESTDIGEST").val(), 
      "Accept": "application/json;odata=verbose", 
      "Content-Type": "application/json; odata=verbose" 
  success: function (data) { 
    if (data.d.results) { 
      // TODO: handle the data  
      alert('handle the data'); 
  error: function (xhr) { 
     alert(xhr.status + ': ' + xhr.statusText); 

But if you need to do that, I don’t see why you wouldn’t just use SOAP.

User Voice: Add support for recurring events in the REST API

Lookup Site Columns in Other Webs

A good information architecture usually includes some list-based lookup columns. A simple example might be a list stored in the root site of a Site Collection to contain information about all of your organization’s offices. You might store things like:

  • Name of Office (using the Title column)
  • Address
  • City
  • State
  • Postal Code
  • Office Manager
  • Phone Number
  • Industry Focus
  • etc.

Then you might have a Site Column called Office Name that is a Lookup column into the Title column of that list. This enables you to offer a consistent list of options for Office Name to choose from throughout the Site Collection along with the other information (as needed), either for display purposes or for inclusion as data in other lists.

If you try to make a REST call which requests data in a column like this – when you aren’t in same site as the list – you’ll get an error like this:

Uh-uh, it’s back to SOAP again.

User Voice: Enable support for lookup columns in other webs in the REST API


In case you were going to ask, I avoid CSOM/JSOM. I see it as a dead end – in this context, at least. More of Microsoft’s effort is going into REST, which is based on Web standards rather than a Microsoft-only approach.

What about you? Do you still see uses for SOAP where REST won’t do it? Respond in the comments if you know of other holes in the REST Swiss cheese.



  1. Great post!

    I recently had to fall back onto the old Copy.asmx web service to copy a document between two libraries, where the destination library had versioning enabled, and an the file being copied already exists in the destination (so basically copying new versions of a file and want the version history to increment properly).

    The REST service to copy a file will simply either point blank overwrite the file in the destination library if it exists, thus starting from version 0.1 again and losing all the previous version history. Or, if you set the bool flag for overwrite to false, it gives you a nice error :). So copy.asmx was the only way I could get the doc it to copy and the result being a proper version increase.

    There’s some others I’ve run into as well, I’m using Nintex workflow a lot for clients right now and tried to replace any places I’d previously use the SOAP web services with the REST equivalents – but sometimes odd instances like this do come up and it’s definitely not fully up to scratch yet, particularly for less common combinations of settings such as the above.

  2. There is an example of using CAML in the request body rather than the querystring here: Same thing, but it just looks cleaner to my eyes.

    Also, for the lookup columns, if you use the cross-domain library, you can get the id value from the lookup column, then look up the target value up by id in the source list. One can argue that it’s less efficient when an extra call is made back to the server for each item, but if the lists involved aren’t huge, then I would argue that it’s no biggie. If a LOT of calls are made, one can “cache” the id’s and values in a hashtable during onload and really speed things up, depending of course how many values are being pulled. Of course, all things are relative…


Have a thought or opinion?