SharePoint Designer 2013 Workflow: Working with Web Services

SharePoint Server 2013 offers a completely new architecture for Workflow utilizing Workflow Foundation 4.5.  I’ve already covered the high-level changes in a previous post called “What Changed in SharePoint 2013 Workflow? Pretty Much Everything” and discussed how a SharePoint 2010 Workflow project would be designed differently in my post titled “Redesigning a SharePoint 2010 Workflow Project for SharePoint 2013.”  Both of these posts discuss the new reliance on web services for data in SharePoint Workflow.  While it’s obvious that Visual Studio workflows would interact with web services, SharePoint Designer 2013 offers web service communication, as well.  This post will detail the new actions available in SharePoint Designer 2013 for interacting with web services and how to use them. New SharePoint Designer Objects – Call Web Service and Dictionary

SharePoint Designer 2013 introduces four new actions that you’ll use when accessing data via web services.

  • Call HTTP Web Service
  • Build Dictionary
  • Count Items in Dictionary
  • Get Item from Dictionary

The “Call HTTP Web Service” action is the action used to actually make the request to a service.  There are several parameters that can be set including: request body, request headers, response content, response headers, URL, and HTTP method.  While I won’t go into the details of HTTP response and request, you can read up on it here, you’ll need to know that both the request and response headers and contents will use the new Dictionary objects to provide or contain them.

The Dictionary object allows you to store an array of key/value pairs.  These pairs can be used to store many types of data such as business objects like Employee or Client.  In the context of web service interaction, they’ll hold the header properties or content data passed to and from a service.  The three actions noted will allow you to create a Dictionary object (Build Dictionary), get the number of items in a Dictionary, and get a specific item from the Dictionary.  In the next section, you see how these are used.

Accessing Web Services – An Example

Create Site Workflow in SharePoint Designer 2013

Image 1 - Creating a SharePoint 2013 Site Workflow named Demo.

The example for this post will be using the SharePoint 2013 web services to get a collection of items from a list, log the number of items, and log the newest item’s title.  This will be a Site workflow instead of a List workflow since it doesn’t really need to be fired when items are created or modified.  This will be split into 3 different workflow stages: Get Security Context, Get List Data, and Log Information.


Stage One: Get Security Context

When working with the SharePoint REST services you need to authenticate the requests.

Request Header Dictionary properties for Context/Security Token service call.

Image 2 - Three headers are required to get the token: Content-Type, Accept, and Content-Length.

There is a service available to take care of this.  This step will build a Dictionary object for the request headers and then call the service to get the security token.  First we’ll create a new Dictionary action, output it to a variable called contextHeaders, and create entries for Accept, Content-Type, and Content-Length headers.  For Accept and Content-Type, we want to use “application/json; odata=verbose.”  SharePoint 2013 REST calls require the second parameter, “odata=verbose,” because while the OData specification supports other options, SharePoint’s services do not.

Next, we’ll create a “Call HTTP Web Service” action to get the token.  In Image 3, you see the URL to get the token is using the new /_api path to the SharePoint REST services.

Configure the URL to get the token.

Image 3 - The URL is <your site>/_api/contextinfo and MUST be a HTTP POST method.

Also, you must use the POST method to get this token.  While you would expect to use a GET call, the reason for POST is to improve security against “shady” requests.  Next, we’ll need to assign a variable to the ResponseContent of the action.  This is a Dictionary object we’ll call contextResponse.  Finally, we need to set the RequestHeaders property of the action to our contextHeaders dictionary.

Properties window for the Call Web Service action.

Image 4 - Set the RequestHeaders property to the contextHeaders variable.

Right-click on the action and select “Properties…” to access the action’s properties window.  Also, we’ll set the Transition to stage section to “Get List Data.”

Stage Two: Get List Data

This stage will get the token value, build the request headers, and get the list data.  First, we’ll get the token from the contextResponse variable.  To do this, create a Get an Item from a Dictionary action.  As you see in Image 5, we provide a path to the FormDigestValue entry of the contextResponse of “d/GetContextWebInformation/FormDigestValue” and save it to a string variable called digestValue.

Path for DigestValue.

Image 5 - The path for the digest value is d/GetContextWebInformation/FormDigestValue.

Next, we build another Dictionary object called getHeaders.  This is similar to the contextHeaders except we don’t use Content-Length and we include X-RequestDigest, which is set to our digestValue.

X-RequestDigestValue example

Image 6 - X-RequestDigestValue is set to our digestValue variable.

We then create our call to the list using a GET Method, storing the ResponseContent in a Dictionary called getResponse and setting the RequestHeaders in the action’s properties (see Stage One above) to getHeaders.  You’ll note that our URL has select and orderBy parameters on the end of it.  This is so we get just the data we need (Title in this case) to keep the response size as small as possible as well as ordering it from newest entries to the oldest.

Configuring the service call to get the list items.

Image 7 - The URL to the list is <your site>/_api/web/lists/getbytitle('<your list name>')/items.

Finally, we’ll transition to the Log Information stage.

Stage Three: Log Information

Our final stage will log the number of items in the list and the newest item’s title to the Workflow History list.  The getResponse Dictionary has a tree structure with the actual list item data not being at the root of that tree.  The data is actually in a node called “results.”

An example of the list items response as JSON.

Image 8 - The data returned is in JSON and the results are nested under the root (d) in the results node.

To get our count, we need to extract that node, a Dictionary itself, from getResponse.  We’ll create another Get an Item from a Dictionary action that saves this collection of results from getResponse to a new Dictionary called listItems using a path of “d/results”.  We can then use a Count Items in a Dictionary action to store the number of results in listItems to an Integer variable called count and then log that to the history list.

Next, well get the Title of the newest record which, because of the orderBy on the request URL in the last stage, is the first record.  We’ll create our third Get an Item from a Dictionary action with a path of “(0)/Title” from our listItems Dictionary and store it to a string variable of newestRecordTitle.  We use “(0)” to get a record at the first position in the collection.  If you’re wondering why it’s 0 and not 1, the reason is that collections, or arrays, in most modern programming languages use 0-based arrays.  We’ll log that to our history list and transition the stage to End of Workflow.

Example Results

After publishing, I ran the workflow in my Office 365 site and as you can see in Image 9, it produces exactly what’s expected.

Results of the workflow after running it.

Image 9 - Our expected output is logged and the workflow has completed successfully.

The Internal Status is Completed and we have three records in the Workflow History list: our FormDigestValue (most is blacked out to protect my environment), the total records in the list, and the newest item’s title.

Conclusion

While this wasn’t a real world example, it should help you understand how to use the new actions that are available for working with web services.  Even though I used SharePoint’s web services, these will work with others.  For instance, let’s say you have a site where you track Sales leads.  Once a lead reaches a certain stage (i.e. “Request for Proposal created”), then you want to create the client and/or project in your Microsoft Dynamics CRM or Salesforce system.  These products offer services that you could use to create these through the workflow.  Your organization may have web services it uses for custom developed solutions.

All of the steps in the workflow.

Image 10 - All of the steps in the workflow.

In this case, you should be able to interface with those services to push data to or pull data from those applications in the same way (consult the development team on how to use these).

About Sam Larko

Sam Larko has been working with SharePoint for six years and across the last three versions. While his experience is primarily in development, Sam has become more involved in administration and architecture over the last three years. In addition to SharePoint, he has a strong desire to become involved in mobile development, especially Android and Windows Phone.

  • Jimmy Jimenez

    Hello,

    I’ve created a workflow that updates an item in a parent site from sub-site. This works. Then I save the sub-site as template and create a new sub-site based on that template.
    When I fire the workflow I get Unauthorized error. Even if I send Authorization: bearer and X-RequestDigest in the header.

    Do you know what i’m missing? Any help will be appreciated
    Thanks in advance,
    Jimmy

  • Amay

    I am also facing the forbidden error but not able to trace why?, please help on it

  • Ilya Svergin

    Very helpful article. Thank you!

  • Maicon Martins Felicio

    Hi, i’m have an issue by try create a listitem by List Workflow in a subsite and create item in a parent site that is a parentweb from currentSite.

    I already set it up this configuration :

    I can’t get digestvalue. The website that i try add item has “https” protocol, if i test by chrome web extension called “Restlet client” a http request with protocol “http” it works, but if i test with “https” throw error “forbidden” .

    Could somebody help me?