Custom Workflow Activity for Creating a SharePoint Group

In my last post I looked at how to create a custom workflow activity in Visual Studio 2012 for creating sites in SharePoint 2013. In this post I'll show you how to build a workflow activity that creates a SharePoint group.

Note: this is part of a series of posts on building workflow activities to manage sites, groups, users and permissions. For a complete list of posts, together with a more detailed walkthrough of how to build a custom workflow activity and make it available in SharePoint Designer, start at the beginning.

Fundamentals

You can use the REST API to create a new SharePoint group. You need to send a web request that resembles the following:

Endpoint:
{site collection URL}/_api/web/sitegroups

HTTP method:
POST

Headers:
Accept: application/json; odata=verbose
Content-Type: application/json; odata=verbose

Body:
{   "__metadata":{
      "type":"SP.Group"
   },
   "Title": "Project One Owners",
   "Description": "Members of this group have full control on the Project One site"
}

Build the XAML File

I'm going to assume that you know how the basics of how to build custom workflow activities for SharePoint in Visual Studio 2012 - if you don't, take a look at my previous post. As I did last time, I'll start by defining the arguments for the workflow activity:













In this case, I want the consumer of the workflow activity to provide a title and a description for the new group - that's all the information we need. The workflow activity will return the integer ID and the login name of the new group - the consumer might need one or the other, depending on what they want to do after creating a group. We'll also return the response status code returned by the call to the REST API, to help out the activity consumer in the event that something goes wrong.

Next, I'll define the variables I want to use within my activity:














In practice, you're probably not going to know all the variables you need when you start developing a workflow activity. However, if you're replicating these steps to create your own activity, it's probably easier to define them all up front.

We can now start building the activity by dragging child activities from the toolbox onto the designer surface. The finished activity looks like this:








































As you can see, the activity consists of seven child activities. Let's run through each of these in turn.

Step 1: Get current site URL
In this activity, we want to get the URL of the current site collection. I've used a LookupWorkflowContextProperty activity to do this. In the activity properties, I'm looking up the current site URL and assigning it to the siteUrl variable.















Step 2: Build the REST URL
In this activity, we want to build on the site URL to form a REST endpoint for our request. I've used an Assign activity to do this. In the activity properties, I'm concatenating the site URL and the site-relative REST endpoint, and assigning the result to the restUrl variable.














Step 3: BuildDynamicValue (jsonRequest)
In this activity, we build the JSON body for our REST request. I've used a BuildDynamicValue activity to do this.
















To define the properties in the jsonRequest variable, click the ellipsis in the Properties row. This enables you to provide a set of key/value pairs:


















Notice the Entity Type dropdown at the top of the dialog box. This doesn't change the structure of the variable you're creating in any way - it's a convenience tool that enables you to select your Path values from a list, rather than typing them manually. As we covered last time, you can use XPath notation (e.g. "__metadata/type") to add nested values to the variable.

Step 4: Call the REST API method
We've now set all the variable values we need, so we're ready to call the REST method. I've used the HttpSend activity to do this. You can configure every aspect of the request through the activity properties pane:

























In this case, I've:
  • Set the HTTP Method to POST.
  • Set the content of the request to the value of our jsonRequest variable.
  • Set the Uri for the request to the value of our restUrl variable.
  • Assigned the response body to the responseContent variable (this is a DynamicValue instance, because we're expecting a JSON response).
  • Assigned the response headers to the responseHeaders variable (again, a DynamicValue instance).
  • Assigned the response status code to the responseStatusCode variable (an HttpStatusCode enumeration value).
The other thing you need to do here is to configure the request headers for the service call. To do this, click the ellipsis in the RequestHeaders row. This enables you to define your request headers as key/value pairs:


















Step 5: Assign responseStatusCodeOut
At this point in the execution of our workflow activity, we've called the REST API method and a new group has hopefully been created. Now all we need to do is extract any information we need from the HTTP response. In this Assign task, I'm taking the responseStatusCode variable, converting it to a string, and assigning it to the responseStatusCodeOut argument. As I mentioned last time, SharePoint Designer doesn't like complex types like HttpStatusCode and DynamicValue. If you want to return information to SharePoint Designer, you need to convert your properties to an SPD-friendly type. In this case, we simply call the ToString method on our responseStatusCode variable and assign it to the String-based responseStatusCodeOut argument:













Step 6: Get new group ID
We want to return the integer ID and the login name of the new group to consumers of our workflow activity. We can get both of these properties from the JSON response returned by the REST API. If you look at the response in Fiddler (or any other web debugger), it should resemble the following:
{"d":{
   "__metadata":{
      "id":"http://team.jason.net/_api/Web/SiteGroups/GetById(27)",
      "uri":"http://team.jason.net/_api/Web/SiteGroups/GetById(27)",
      "type":"SP.Group"
   },
   "Owner":{
      "__deferred":{
         "uri":"http://team.jason.net/_api/Web/SiteGroups/GetById(27)/Owner"
      }
   },
   "Users":{
      "__deferred":{
         "uri":"http://team.jason.net/_api/Web/SiteGroups/GetById(27)/Users"
      }
   },
   "Id":27,
   "IsHiddenInUI":false,
   "LoginName":"Project One Owners",
   "Title":"Project One Owners",
   "PrincipalType":8,
   "AllowMembersEditMembership":false,
   "AllowRequestToJoinLeave":false,
   "AutoAcceptRequestToJoinLeave":false,
   "Description":"Members of this group have full control on the Project One site",
   "OnlyAllowMembersViewMembership":true,
   "OwnerTitle":"Administrator",
   "RequestToJoinLeaveEmailSetting":null
}}

Now that we know what the response will look like, we can use GetDynamicValue<T> activities to extract the properties we want from the JSON response. To get the group ID, we use specify the path "d/Id":














Step 7: Get new group login name
Similarly, we can use a GetDynamicValue<T> activity to get the login name of the new group. In this case, the path is "d/LoginName":















Build the Actions File

Our last task is to edit the .actions4 file so we can use the Create Group activity in SharePoint Designer. To recap, the .actions4 file defines the sentence that appears in SPD when you add the activity to a workflow, together with the arguments defined in the workflow activity. (For a more detailed explanation of how it works, see the previous post.)

In this case, the .actions4 file should resemble the following:
<Action Name="Create Group" ClassName="SiteManagementActivities.CreateGroup" Category="Site Management" AppliesTo="all">
  <RuleDesigner Sentence="Create a site group named %1 with description %2 (Output: %3 %4 %5)">   
    <FieldBind  Field="groupTitle" Text="Group Title" Id="1" />
    <FieldBind  Field="groupDescription" Text="Group Description" Id="2" />   
    <FieldBind  Field="groupIdOut" Text="Group ID" Id="3" />
    <FieldBind  Field="responseStatusCodeOut" Text="Response Status Code" Id="4" />
    <FieldBind  Field="loginNameOut" Text="Group Login Name" Id="5" />
  </RuleDesigner>
  <Parameters>
    <Parameter Type="System.String, mscorlib" Direction="In" Name="groupTitle" />
    <Parameter Type="System.String, mscorlib" Direction="In" Name="groupDescription" />   
    <Parameter Type="System.Int32, mscorlib" Direction="Out" Name="groupIdOut" />
    <Parameter Type="System.String, mscorlib" Direction="Out" Name="responseStatusCodeOut" />
    <Parameter Type="System.String, mscorlib" Direction="Out" Name="loginNameOut" />
  </Parameters>
</Action>

And that concludes how to build a workflow activity that creates a SharePoint group. Next time, I'll take a look at how to set the owner of a group from a workflow activity.

Update 17/11/14: a sample Visual Studio solution containing these workflow activities is now available for download.

Comments

Popular posts from this blog

Server-side activities have been updated

The target principal name is incorrect. Cannot generate SSPI context.

Custom Workflow Activity for Creating a SharePoint Site