locked
How to use WF4 in code with WCF Service RRS feed

  • Question

  • Hi Guys

    I am new to WF and need some help in the right direction. I want to use WF in code but still expose it trough WCF servcies. I cant find any good documentation on the subject...

    I usually create a servciehost project to host my .svc file in IIS. In the markup I point to my code library where I have my functions...this works great for my WCF services but I am not getting this to work properly with WF..this is my markup in svc file:

    <%@ ServiceHost Language="C#" Debug="true" Service="WF_SetviceTest.Activities.SendRequest.cs" Factory="System.ServiceModel.Activation.WorkflowServiceHostFactory" %>

    but i always get the following error message when I try to view in browser:

     

    WorkflowServiceHostFactory cannot resolve the constructor string 'WF_SetviceTest.Activities.SendRequest.cs' to a  workflow type. The constructor string must contain either a name of the *.xoml file or a CLR type name of the workflow service type. 

    I know I am missing something....but what..

    Can any of you point me in the right direction for documentation on the issue??

    Regards

     

    Wednesday, June 2, 2010 9:52 AM

Answers

  • Hi hekla,

    You certainly can host WF code activity as a service through svc file. There are 2 issues in your svc file:

    1) I think you used wrong factory class. System.ServiceModel.Activation.WorkflowServiceHostFactory is for WF 3.5. You can still use it in .Net 4, but it only recognize WF 3.5 activities.

    If you want to host WF4 service, please use System.ServiceModel.Activities.Activation.WorkflowServiceHostFactory

    2) The service attribute should be set with the activity type name instead of .cs file name.

     

    I've tried and it works pretty well to me. Please let me know if it does not work for you:)

    thanks

    Anders


    This posting is provided "AS IS" and confers no rights or warranties.
    Friday, June 4, 2010 8:36 AM

All replies

  • If you want to host the WCF Service then remove the Factory statement. Then you can call you workflow in you code.

    You only specify the Factory is you want the WCF Service to host the Workflow directly. 

    Wednesday, June 2, 2010 10:58 AM
  • Hi cecilid

    O, thanks for that :) But I wonder, what are the benefits of not hosting the Wf directly as a servcie? I want to use coded WF with Recevie and Send activities, Bookmarks, Persistence etc... What is the best solution for me to use? WCF (and call the WF in code) or WF Services?? 

    I tried to setup svc file (that uses Factory element) to test.. I get the following Error:

     

    Passed in type is not a valid Activity.
    Parameter name: workflowType

    still I start my WF(in code) with Receive activity. 

          //Create the Receive activity
          var reciveRequest = new Receive
                      {
                        ServiceContractName = "IContract",
                        OperationName = "ReciveMessage",
                        CanCreateInstance = true,
                        Content = ReceiveContent.Create(new OutArgument<RequestMessage>(request)),
                        CorrelatesWith = requestHandle
                      };


    Regards

    Thursday, June 3, 2010 8:57 AM
  • Use the Workflow Console Application project template, In program.cs you can create your service through code(coded workflows in WF 4.0 dont have designers) as well as host it programitically using workflwoServiceHost.

    Refer this sample from microsoft:

    ~\WF_WCF_Samples\WF\Basic\Services\DurableDelay

    ~\WF_WCF_Samples\WF\Basic\Services\ContentBasedCorrelation

    Other more simpler way is to create a project of type WCF Workflow Service Application. You will find this template under WCF and under WF tab also. In this project you will get default service with name Service1. It will have designer also and its extendion will be xamlx which denotes that it is a WCF service. Right click Service1.xamlx and select View in browser and you will be able to see the service url and its wsdl also.

    refer this sample from microsoft:

    \WF_WCF_Samples\WF\Basic\Services\XAMLService

    Hope this helps.

    • Proposed as answer by Sneha Gupta Tuesday, June 8, 2010 4:59 AM
    Thursday, June 3, 2010 9:21 AM
  • Hi Suchi

     

    I have looked at these samples :) but there is no sample on how to host the WF in IIS as a Service :(

    I am building a enterprise application where all clients  (several clients based on MVC, Silverlight and Win Forms) connects to the server trough WCF Services.

    I would like to imp WF for several operations but I would prefer to use coded WF in stead of creating them in the designer. All services are hosted in IIS (Win Server 2008 R2) but I can't do that with Console application :|

    Any idea on good documentation on the subject??

     

    Regards

    Thursday, June 3, 2010 9:40 AM
  • The declarative workflow service you create can always be hosted on IIS and will behave just like a WCF service with Receive activitis as operation contracts and any of  the client(MVC, Silverlight, WinForms) can make a call to this service just like they make a call to the wcf service.

    The WCF service application project you created, rght click it, select properties, select the web tab, and select radio button "Use local IIS Web Server". Immediately Visual studio will create a virtual directory in IIS and will host your service on IIS. Browse it , to verify the URL. You need to open Visual Studio with elavated priveledges to set this property.

    If you create coded workflows , you need to host them programitically using WorkflowServiceHost.

    • Proposed as answer by Sneha Gupta Thursday, June 3, 2010 12:37 PM
    Thursday, June 3, 2010 12:37 PM
  • Hi hekla,

    You certainly can host WF code activity as a service through svc file. There are 2 issues in your svc file:

    1) I think you used wrong factory class. System.ServiceModel.Activation.WorkflowServiceHostFactory is for WF 3.5. You can still use it in .Net 4, but it only recognize WF 3.5 activities.

    If you want to host WF4 service, please use System.ServiceModel.Activities.Activation.WorkflowServiceHostFactory

    2) The service attribute should be set with the activity type name instead of .cs file name.

     

    I've tried and it works pretty well to me. Please let me know if it does not work for you:)

    thanks

    Anders


    This posting is provided "AS IS" and confers no rights or warranties.
    Friday, June 4, 2010 8:36 AM
  • Hi Anders,

    Even i tried same and it worked.

    Thanks

    Friday, June 4, 2010 10:11 AM
  • Hi Anders,

    But what are the advantages/Disadvantages/Limitations of invoking a workflow activity through WCF service svc file, rather than creating a Declarative Service(Xamlx).

    Thanks

    Suchi

    Friday, June 4, 2010 10:18 AM
  • Hi Anders

     

    Now I have tried to make this work without luck :( I have created a simple example solution with 3 projects.

    1. WCF Servicehost with a single .svc file with following markup:

    <%@ ServiceHost Language="C#" Debug="true" Service="WFCodeTest.Workflows.SendWF" Factory="System.ServiceModel.Activities.Activation.WorkflowServiceHostFactory" %>

    2. Project for contracts.. IContract and 2 different classes that are user as messages in WF.

    3. Workflows. One class for Send activity:

    public sealed class SendWF : Activity
      {
        public InArgument<string> Name { get; set; }
        public InArgument<int> Age { get; set; }
    
        public SendWF()
        {
          var request = new Variable<RequestMessage> {Name = "request"};
    
          var send = new Send
                  {
                    OperationName = "SendRequest",
                    ServiceContractName = "IContract",
                    EndpointAddress = new InArgument<Uri>(env => new Uri("http://localhost/CodeTestService")),
                    Endpoint = new Endpoint
                           {
                             Binding = new BasicHttpBinding()
                           }
                  };
    
          //Define wf
          this.Implementation = () => new Sequence
                          {
                            DisplayName = "MessegeTest",
                            Variables = {request},
                            Activities =
                              {
                                new WriteLine
                                  {
                                    Text = new InArgument<string>(env => "Message received from " + Name.Get(env).ToString())
                                  }
                              }
                          };
        }

    and one receive class: 

      public sealed class RecevieAssaignment : Activity 
      {
        public RecevieAssaignment()
        {
          var request = new Variable<RequestMessage> {Name = "request"};
          var response = new Variable<ResponseMessage> {Name = "response"};
    
          var receive = new Receive
                   {
                     OperationName = "RevevieMessage",
                     ServiceContractName = "IContract",
                     CanCreateInstance = true,
    
                     Content = ReceiveContent.Create(new OutArgument<RequestMessage>(request)),
                   };
    
          this.Implementation = () => new Sequence
                          {
                            DisplayName = "Recevied Message",
                            Variables = {request},
    
                            Activities =
                              {
                                receive,
                                new WriteLine
                                  {
                                    Text =
                                      new InArgument<string>(
                                      env =>
                                      "Recevied request from: " + request.Get(env).Name)
                                  },
                                new SendReply
                                  {
                                    Request = receive,
                                    Content =
                                      SendContent.Create(
                                        new InArgument<ResponseMessage>(response))
                                  }
                              }
                          };
        }
      }
    but where do I invoke WorkflowServiceHost etc when I only use svc file to host in IIS?? I do get the svc file up in the browser but no wsdl markup when I try to click the definition  :(

     

    Regards

     

    Friday, June 4, 2010 12:04 PM
  • Hi hekla,

    Actually, Suchi is right. Why don't you create a simple xamlx file that just contains one activity, which is your code activity contains Receives. Then you just publish the xamlx file and use it to access your service.

    thanks,

    Anders


    This posting is provided "AS IS" and confers no rights or warranties.
    • Proposed as answer by MuazzamAli Monday, July 26, 2010 8:01 PM
    Monday, June 7, 2010 2:28 PM
  • Please take a look at this article:

    Building and testing WCF web service using workflow foundation 4.0

    http://www.codeproject.com/KB/WF/WCFServiceUsingWF.aspx

    Monday, July 26, 2010 8:02 PM