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 | “” |
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 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-e14e0e7aConclusion
MSDN has good numbers of examples available to start with workflow. Let me give you some links to these examples that might be helpful:- Dynamic Value Path Evaluator: Use this code example to understand how to parse the response from service
- Workflow Resource Browser: Browse workflow server resources
I cannot access my customized WCF Service deployed on MOSS2013. HTTPCode is badrequest. Have you enabled your WCF service access anonymously?
ReplyDeleteAccessing WCF service is not related to anonymous access. If your WCF service deployed properly, you should be able to access the WCF service. You can download the code for this post from msdn code gallery and find out if the WCF service works.
ReplyDeleteI can access right now. Thank you so much:)
DeleteTwo tight details:
1. Using SharePoint default factory 'Microsoft.SharePoint.Client.Services.MultipleBaseAddressWebServiceHostFactory, Microsoft.SharePoint.Client.ServerRuntime, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c' in WCF .svc
2. Add Authorization="" to RequestHeaders property at HttpSend action
This comment has been removed by the author.
DeleteI've been getting Bad Request 400 response. The solution is to change the Factory in .svc file to use MultipleBaseAddressWebServiceHostFactory used for REST services instead of MultipleBaseAddressBasicHttpBindingServiceHostFactory that is used for SOAP services.
ReplyDeleteThank you, really, THANK YOU!
DeleteWhere can I get Microsoft.SharePoint.Client.ServerRuntime.dll? I have downloaded SharePoint Server 2013 Client Components but it's not there. Thanks
ReplyDeleteI used LookupWorkflowContextProperty -> Current Site to get the site URL which I expected to be http://xzy.local/ but instead it returned http://xyz.local/pm my Project Management sub-web. Do you know any other way in 2013 Workflow to return the site collection url? Thanks Sohel
ReplyDelete@Russell, As I can remember I couldn't find any property to get Site Collection Url. Maybe it's by design as workflow will be executed under current site context?
ReplyDeleteHi Sohel, I was getting 401 error while calling custom WCF service (Hosted in SP) from workflow. Based on code you shared I changed the request header autherization with "" and it's working fine. I just want to know this is the only solution did you find or any other solution also available for same problem. Please also help me to know your opinion to set request header autherization ="" for production environment.
ReplyDelete@Sourabh, the idea of using Authorization header to empty string can be found at http://social.msdn.microsoft.com/Forums/windowsazure/en-US/d3b8dd8f-a1ab-4a52-be58-dfb3e1f2b2eb/httpsend-to-call-custom-wcf-service?forum=wflmgr
ReplyDeleteGreat Post Sohel, all is working well.
ReplyDeleteMy only issue is that when I invoke the WCF service from the HttpSend activity, the WCF service always runs in the context of the account which is the service account of the Workflow Manager. It never runs with the context of the current logged in user.
When I do SPContext.Current.Web.CurrentUser inside the service, I always get the service account of the Workflow Manager. However, If I call the service from the browser, the correct user is returned so the issue is not with the WCF service.
My guess is that it has to do something with the Authorization header being set as "". Do you have any idea?
Vardhaman, I'm not sure but I reckon this is expected. Workflow Service is running under the workflow service account and I expect workflow manager doesn't impersonate the service call. You can dig dipper into the problem or you can go for a simple solution - pass the current username/id in the service call and impersonate the code with the passed user.
ReplyDeleteYes Impersonating the user by passing the credentials is a workaround I am already considering.
DeleteJust was curious as to why the service call was not made from the current user's context by the workflow manager.
Frist thank you for this great effort it help me in WCF creating and call , but i need to ask you about set workflow status activity in SharePoint 2013 , because i couldn't find it in tool box, and also couldn't do it as custom activity.
ReplyDeletethanks in advance
@abdelmohsen, I think it's not shown by default. Try to browse and add the SharePoint Designer activities dll from workflow installation directory (mabye in program files directory)
ReplyDeletethanks to replay.
DeleteI add the Microsoft.sharepoint.desgin.activity and i can get it.
I have tested HTTPSend activity's authorization attribute as "" with HTTPs site (Site and workflow service app both are running on HTTPs) and it's working fine.
ReplyDeleteI was also getting the bad request. To fix it make sure you not only use MultipleBaseAddressWebServiceHostFactory but use the 15.0.0.0 version. I was getting error because I was using 14.0.0.0 version.
ReplyDeleteHi Sohel,
ReplyDeleteCan we call a Windows Service using httpSend activity in SharePoint 2013?