PortiBlog

SharePoint Designer Call HTTP Web Service to create item in other Site (Collection)

3 november 2016

What?

Summary: this post is to show how you can use SharePoint Designer (2013) to create an item in another list in another site (collection).

If you have ever tried to support a business process within SharePoint with one of the default workflow functionalities, you probably came to the conclusion that you would need to build everything in the same site as there are no ready-to-use actions in a SharePoint Designer Workflow to create a list item in another site or another site collection. I would like to show how you can support the business better by creating items from one site to another site by using the default SharePoint Designer 2013 Workflow actions.

Why?

In some business processes that you want to support with SharePoint, it may occur that there are existing SharePoint Sites where permissions are already exactly configured as desired by business owners and where (even more important) these business owners are already managing access to their sites themselves (preventing those frequent requests to a support department to provide access to certain persons). Would it not be great to make use of these existing sites instead of creating separate sites where access needs to managed separately, just to support specific business processes??

In my case I not only wanted to prevent an extra site to be created, but I wanted to create an environment where one department site would have a ticketing system (SharePoint List) where in the future other multiple departments would also be able to have tickets created from their sites.
http_call_spd_00_businesscase

(yes... I made this drawing in OneNote off course!)

How?

First let me clarify that SharePoint Designer 2013 is needed and the SharePoint environment will need to have the 2013 Workflow engine working as this will make the Call HTTP Web Service action available in your workflow. This setup should work in SharePoint Online (Office365 - even though PowerApps and Flow will probably make this easier in the nearby future) as well as a SharePoint 2013 and higher On Prem environment. I recommend to get this working in the same site first and then from one site to another, to make troubleshooting easier when the call is not working.

My journey started with a blog post: Using SharePoint REST services from workflow with POST method showing us how this could be achieved, but a non-technical specialist (like myself) wanted to know more about why certain actions where needed and in my test case some essential steps were missing / not explained enough.

Basically there are 2 steps:

  1. Make sure your workflow from the source site (where your workflow is published) is able to perform actions on the target site
    (in the MSDN post: Create a workflow with elevated permissions by using the SharePoint 2013 Workflow platform it is stated that workflow must be published before granting permissions and the user that grants permissions must have Site Owner permissions, but later on in the same post it is stated that permissions are granted to the Workflow app in general and not just a specific workflow. Individual workflows cannot be access controlled. When you enable app permissions you are enabling for all workflows within the Site Collection so I would not see a need to publish the workflow first)
  2. Create a workflow in your source site with the desired Call HTTP Web Service action

Let me explain these steps in more detail:

  1. Make sure your workflow from the source site (where sending / posting workflow is published) will be able to perform actions on the target site
  1. In Manage site features of source site enable the feature of "Workflows can use app permissions"
  2. This will add a record to the Site app permissions which can be found in Site Settings of your source site
    http_call_spd_01_sitesetting_workflow_app_permisions
    Copy the App identifier (ID between last | and @) for next steps (n my example this was 8f20f240-ddde-45dc-a08a-66834769220d)
  3. Repeat step 1 for the target site to enable the same feature here
  4. Add a record manually to the Site app permissions of the target site by visiting the hidden Grant permission to an app page.
    This must be done by browsing to the appinv.aspx page of the site. Example: http://{hostname}/{the Site Collection}/{possible subsites}/_layouts/15/appinv.aspx.
    Paste your App identifier of the source site, lookup the rest of the information and use the following XML to the App's Permission Request XML.
    <AppPermissionRequests>
    <AppPermissionRequest Scope="http://sharepoint/content/sitecollection/web" Right="FullControl" />
    </AppPermissionRequests>

    The record will be something like:
    http_call_spd_01_sitesetting_workflow_app_record

  5. Give it a Title that will let you know which "App" this record about granting permissions is about - this will be very useful when you will have multiple source sites creating items in the same target site.
    I gave it the name Workflow from Source 1 and the last page before creation will be the confirmation to trust this app: 
  • IMPORTANT: If you disable the feature on the source/target site the call will not succeed or the configuration may even break with the notification in the workflow of "Retrying last request. Details of last request: HTTP InternalServerError to..." and "Invalid text value"

2. Create a workflow in your source site with the desired Call HTTP Web Service action

  • Because the workflow is started when an item in the source site is created, the list of the source site will be the list where the workflow is to be created:
  • a prerequisite is a source list in the source site:
  • that will have a workflow
 
  • creating an item in the target list

  • Let me show you the end result of the workflow first and then explain the steps in detail:


I use as much variables as possible because I always want to create a workflow that is reusable and/or changeable without having to republish the workflow for smaller changes / edit all the actions where the same data is used:

  • TargetSite00URL is the clean url of the target site
    (example = https://tenant.sharepoint.com/SC/RESTcallTarget)
  • TargetSite01ListName is the display name of the target list
    (example = TargetList)
    IMPORTANT: because this is the display name, you need to update the workflow if the list name changes
  • CallDesiredAction is the defining action on what to do and the syntax for this purpose =
    SP.Data.[title of target list]ListItem
    (example = SP.Data.TargetListListItem and instead of typing the list title, I used the variable above)
    IMPORTANT: because this is the internal name, you need to be aware that if you change the title of the target list, this one should not be changed and you cannot use the variable anymore
    More info on the possible actions can be found online on sites like this post on MSDN: Get to know the SharePoint 2013 REST serviceGet to know the SharePoint 2013 REST service.
  • CallURL01start is the string used in the HTTP call and the syntax for this purpose =
    [url of target root site][possible target subsites]/_api/web/lists/getbytitle('[title of target list]')/items
    (example = https://tenant.sharepoint.com/SC/RESTcallTarget/_api/web/lists/getbytitle('TargetList')/items and instead of typing the URL-path and the list title I used the variables above)
There are two parts:
  1. Building the required dictionaries for the (REST) web service call with the Build Dictionary action
  • Dictionaries are a new type of variable that supports key-value pairs and in our web service call we need them for:
  • header of the request that consists of two keys that will both have the same value:
application/json; odata=verbose
http_call_spd_02_spd_result_dictionary01
  • metadata that determines the type of call
http_call_spd_02_spd_result_dictionary02
As you can see I have created a variable to determine this value at the start of the workflow. I prefer this because a part of this value is the title of the list and if you want the workflow to be reusable, the title of the target list should be dynamic as explained above.
  • parameters that consists of a combination of the previous dictionary and all fields that you want to be completed with data

http_call_spd_02_spd_result_dictionary03
Note that this Dictionary has a key __metadata (2 x _) that has the value of the (previous) Dictionary metadata and all other key-value pairs are the fields of the target list that you want to have data. IMPORTANT: as you can see in my example where my last field was an existing site column to be completed with data from the current item ==> the key needs to be the internal Database name(KpiDescription) and not the Display name(Description).


2. Call the web service

  • In the previously shared post: Create a workflow with elevated permissions by using the SharePoint 2013 Workflow platform more information is given on having this action wrapped in an App step within the workflow. I guess this is best practice as there is a risk that the workflow initiator may not have permissions on the target list, causing the request to be unsuccessful... if you are sure the workflow initiator has permissions on the target site I would recommend not to use the App step so you can see who created the item in the target site.
    http_call_spd_02_spd_result_webservice_items
    IMPORTANT: the App step is only available in workflows of sites where you have enabled the feature of "Workflows can use app permissions" as explained in the very first step of this guide.
  • The Call HTTP Web Service action in the workflow of the source site is best to be edited using the properties of the action (right-click the action in SharePoint Designer en select Properties) because a lot of settings are correct by default:
    http_call_spd_02_spd_result_webservice_spdcall
  • The RequestType is HTTP POST (also more info on these types can be found online on multiple sites like the post on MSDN: Working with lists and list items with REST)
  • The RequestHeaders is the variable of the dictionary: header
  • The RequestContent is the variable of the dictionary: parameters
  • The ResponseContent and ResponseStatusCode are variables not needed for input so I created these from this step (but not used anywhere else as input in the workflow so for me they are not relevant)

So now you should be able to create items in other lists and if you do more research on the type of calls that can be done, the possibilities will amaze you!

Submit a comment