Sunday, April 28, 2013

SharePoint 2013 Workflow: Use HttpSend Activity to call Custom SharePoint WCF Service

SharePoint 2013 workflow are declarative workflow – means no C# code inside the workflow. All you have in declarative workflow, is predefined activities (or maybe your own custom activities). If you would like to do some very customized things to do in workflow (like verifying data in some external system), you can do so with a WCF service. And then from workflow, you can invoke the WCF. In this post I’ll explain how to create a WCF service and invoke it from workflow. I’ve uploaded the source code in MSDN Code Gallery. Please make sure you have March update for Workflow Manager and Service Bus 1.0 installed, unless the source code might not work properly.

Create a WCF Service

I had described once how to create a WCF service and use it with jQuery for SharePoint 2010 and I’ve created the WCF service based on this post. The workflow Service interface is given below:
[ServiceContract]
public interface IServiceForWorkflow
{
    [OperationContract]
    [WebGet(BodyStyle = WebMessageBodyStyle.Bare, RequestFormat = WebMessageFormat.Json, 
        ResponseFormat = WebMessageFormat.Json, UriTemplate = "/GetData?instanceId={wfInstanceId}")]
    WorkflowData GetWorkflowData(string wfInstanceId);

    [OperationContract]
    [WebInvoke(BodyStyle = WebMessageBodyStyle.Bare, Method = "POST", RequestFormat = WebMessageFormat.Json, 
        ResponseFormat = WebMessageFormat.Json, UriTemplate = "/SendEmail?toEmail={to}&emailSubject={subject}")]
    void SendEmail(string to,string subject);
}

 Code Snippet: Service Interface
As shown in above code snippet, I’ve defined the service method endpoints in UriTemplate. In the UriTemplate, for example /GetData?instanceId={wfInstanceId}, the {wfInstanceId} value is mapped to GetWorflowData method parameter ‘wfInstanceId’. From workflow using HttpSend activity, the service can be invoked as ‘http://serverurl/_vti_bin/ServiceFielName.svc/GetData?instanceId={wfInstanceId}”. The current site url is retrievable from Workflow Context using LookupWorkflowContextProperty activity. Image 1 shows how the HttpSend Activity is used to call the service method from workflow.

Create Workflow

For simplicity, I’ve created a list workflow and once you deploy you need to manually associate the workflow with list/library. You can create either site or list workflow in SharePoint 2013. And if you want you can associate your workflow later instead of development time – maybe through feature receiver. The workflow I’ve created is need to be started manually. To manage workflow development in better ways, I’ve grouped my workflow activities in few groups (parse context values, call wcf service, parse service data etc.) – each group is a sequence of actions.





Use HttPSend Activity to call WCF Service:
To call WCF Service, you need to use HttPSend activity. In this activity you can configure HTTP Verb (GET, POST, MERGE etc.). Since our WCF service will return json data, we need to add two headers (accept and content-type) in the HTtPSend activity to support json data. Also you need to set authorization header to empty string to work properly. Please add the following headers in the HttPSend activity:
Accept "application/json; odata=verbose"
Content-Type "application/json; odata=verbose"
Authorization “”
In the HttpSend activity, the service response returned can be stored in a variable of type DynamicValue. You can read more about DynamicValue at http://msdn.microsoft.com/en-us/library/windowsazure/jj193505(v=azure.10).aspx. The following image shows how you can pass different properties in HttpSend activity:
image
Image 1: HttpSend Activity in use
In the above image, conetent-type and accept header is used to support json data whereas the ‘Authorization’ header is used for WCF service to be invoked properly from workflow.

Parse Service Response:
In the code example provided as part of this post, a workflow variable “WorkflowData” is used to store the returned service response. To retrieve the dynamic data property you can use GetDynamicValueProperty<T> activity, passing the property name. If you have a collection of items returned from service, you can use foreach control block from workflow Toolbox and can apply the GetDynamicValueProperty for each item in foreach. The response from service is stored in a workflow property ‘WorkflowData’ as shown in image 1. The response from service is the object of the following type:
    public class WorkflowData
    {
        public string Subject { get; set; }
        public bool SendEmail { get; set; }
        public string EmailTo { get; set; }
    }

Code Snippet: Workflow data returned from service

The service response is of type ‘WorkflowData’ as defined in above code snippet. To read any property of the ServiceResponse variable (as shown in Image 1) which is of type WorkflowData, GetDynamicValueProperty<T> is used as shown below – where WorkflowData.SendEmail is parsed:
image
Image 2: Parse Service Response property ‘SendEmail’

Finally in the workflow, based on the parsed value (SendEmail property), I’m updating the workflow status.

 

Download Source Code

I’ve uploaded the source code in MSDN code gallery. Please download the source code from http://code.msdn.microsoft.com/SharePoint-2013-Workflow-e14e0e7a

Conclusion

MSDN has good numbers of examples available to start with workflow. Let me give you some links to these examples that might be helpful:
You can get more examples of workflow manager at http://msdn.microsoft.com/en-us/library/windowsazure/jj193482(v=azure.10).aspx.

Wednesday, April 3, 2013

SharePoint 2013: Workflow Error ‘Cannot set unknown member’

I was trying to develop a workflow using Visual Studio 2012 for SharePoint 2013. When I was trying to publish the workflow i was getting the following exception:

Microsoft.Workflow.Client.ActivityValidationException: Workflow XAML failed validation due to the following errors:
Cannot set unknown member 'LookupSPListItem.ItemId'.
HTTP headers received from the server………….

Then after googling i had found the hint in the Microsoft Forum.

 

Solution

Basically you need to re-register the workflow using a Powershell command like below. I think when any Workflow Manager or SharePoint update is installed in the server, these two components get out of sync and re-running the registration will sync both again.

Register-SPWorkflowService -SPSite "SiteURL" -WorkflowHostUri 'WorkflowHostURL'  -Force

Remember to mention Force switch. After the command, restart the Visual Studio or SharePoint Designer and hopefully the issue will be fixed.