title: Workflow hosting engine using Multiple WorkflowServiceHost instances created dynamically
body: <p>I am trying to achieve the following. I have created long running workflows that wake up at scheduled interval i.e. delay activity and perform their job, populate the cache. These workflows are started from main application, which is a IIS 7 hosted custom WCF Data Service. The trigger for starting the workflows vary from User Login, Request for a particular Entity.</p>
  
  <p>Currently, I've created a WCF Workflow Service, that listens for triggers that are part of a standard request contract. Once trigger received, it instantiates a WorkflowApplication with the Activity Definition and starts the workflow. This however has it's limitation, as persistence and rehydration has to be done manually.</p>
  
  <p>I came across the sample of WorkflowServiceHost, which could act as a host that supports Persistence and Rehydration in case of failover, as we have a web farm environment. But, when I tried doing something like the below , It fails with various errors. So just wanted to know, if I am going in the right direction. OR this isn't possible. Please find the IWorkflowCreation contract implementation code based on MSDN sample:</p>
  
  <pre><code>`  public Guid StartWorkflowReturnGuid(Dictionary&lt;string,object&gt; parameters)
          {
              Guid id = Guid.Empty;
              try
              {
  
  
              System.ServiceModel.Activities.WorkflowServiceHost host = new System.ServiceModel.Activities.WorkflowServiceHost(this.workflow, new Uri("net.pipe://localhost"));
  
              //string myConnectionString =
              //   "Data Source=localhost\\SQLEXPRESS;Initial Catalog=DefaultSampleStore;Integrated Security=True;Asynchronous Processing=True";
              //SqlWorkflowInstanceStoreBehavior sqlWorkflowInstanceStoreBehavior =
              //    new SqlWorkflowInstanceStoreBehavior(myConnectionString);
              //sqlWorkflowInstanceStoreBehavior.HostLockRenewalPeriod = TimeSpan.FromSeconds(30);
              //sqlWorkflowInstanceStoreBehavior.RunnableInstancesDetectionPeriod = TimeSpan.FromSeconds(30);
              //host.Description.Behaviors.Add(sqlWorkflowInstanceStoreBehavior);
  
              WorkflowUnhandledExceptionBehavior workflowUnhandledExceptionBehavior =
                  new WorkflowUnhandledExceptionBehavior();
  
              workflowUnhandledExceptionBehavior.Action = WorkflowUnhandledExceptionAction.Terminate;
  
              //Set the TimeToUnload to 0 to force the WF to be unloaded. To have a durable delay, the WF needs to be unloaded otherwise it will be thread as an in-memory delay.
              //WorkflowIdleBehavior workflowIdleBehavior = new WorkflowIdleBehavior()
              //{
              //    TimeToUnload = TimeSpan.FromSeconds(0)
              //};
              //host.Description.Behaviors.Add(workflowIdleBehavior);
              host.WorkflowExtensions.Add(new LoginExtensions());
              host.WorkflowExtensions.Add(new MarketDataExtensions());
              ResumeBookmarkEndpoint endpoint = new ResumeBookmarkEndpoint(new NetNamedPipeBinding(NetNamedPipeSecurityMode.None), new EndpointAddress(string.Format("net.pipe://localhost/workflowCreationEndpoint/{0}",Guid.NewGuid())));
              host.AddServiceEndpoint(endpoint);
              host.Open();
              IWorkflowCreation client = new ChannelFactory&lt;IWorkflowCreation&gt;(endpoint.Binding, endpoint.Address).CreateChannel();
              //create an instance
              id = client.Create(parameters);
              Helper.LogInfo(string.Format("Workflow instance {0} created", id));
              }
              catch (Exception exception)
              {
  
                  Helper.LogError(string.Format("Exception starting BatchWorkflowServiceHost for type {0}", this.workflow.GetType().FullName), exception);
              }
              return id;
          }
  public class ResumeBookmarkEndpoint : WorkflowHostingEndpoint
  {
  
      public ResumeBookmarkEndpoint(Binding binding, EndpointAddress address)
          : base(typeof(IWorkflowCreation), binding, address)
      {
      }
  
      protected override Guid OnGetInstanceId(object[] inputs, OperationContext operationContext)
      {
          //Create called
          if (operationContext.IncomingMessageHeaders.Action.EndsWith("Create"))
          {
              return Guid.Empty;
          }
          //CreateWithInstanceId or ResumeBookmark called. InstanceId is specified by client
          else if (operationContext.IncomingMessageHeaders.Action.EndsWith("CreateWithInstanceId")||
                  operationContext.IncomingMessageHeaders.Action.EndsWith("ResumeBookmark"))
          {
              return (Guid)inputs[0];
          }
          else
          {
              throw new InvalidOperationException("Invalid Action: " + operationContext.IncomingMessageHeaders.Action);
          }
      }
  
  
      protected override WorkflowCreationContext OnGetCreationContext(object[] inputs, OperationContext operationContext, Guid instanceId, WorkflowHostingResponseContext responseContext)
      {
          WorkflowCreationContext creationContext = new WorkflowCreationContext();
          if (operationContext.IncomingMessageHeaders.Action.EndsWith("Create"))
          {
              Dictionary&lt;string, object&gt; arguments = (Dictionary&lt;string, object&gt;)inputs[0];
              if (arguments != null &amp;&amp; arguments.Count &gt; 0)
              {
                  foreach (KeyValuePair&lt;string, object&gt; pair in arguments)
                  {
                      //arguments for the workflow
                      creationContext.WorkflowArguments.Add(pair.Key, pair.Value);
                  }
              }
              //reply to client with the InstanceId
              responseContext.SendResponse(instanceId, null);
          }
          else if (operationContext.IncomingMessageHeaders.Action.EndsWith("CreateWithInstanceId"))
          {
              Dictionary&lt;string, object&gt; arguments = (Dictionary&lt;string, object&gt;)inputs[0];
              if (arguments != null &amp;&amp; arguments.Count &gt; 0)
              {
                  foreach (KeyValuePair&lt;string, object&gt; pair in arguments)
                  {
                      //arguments for the workflow
                      creationContext.WorkflowArguments.Add(pair.Key, pair.Value);
                  }
              }
          }
          else
          {
              throw new InvalidOperationException("Invalid Action: " + operationContext.IncomingMessageHeaders.Action);
          }
          return creationContext;
      }
      protected override System.Activities.Bookmark OnResolveBookmark(object[] inputs, OperationContext operationContext, WorkflowHostingResponseContext responseContext, out object value)
      {
          Bookmark bookmark = null;
          value = null;
          if (operationContext.IncomingMessageHeaders.Action.EndsWith("ResumeBookmark"))
          {
              //bookmark name supplied by client as input to IWorkflowCreation.ResumeBookmark
              bookmark = new Bookmark((string)inputs[1]);
              //value supplied by client as argument to IWorkflowCreation.ResumeBookmark
              value = (string) inputs[2];
          }
          else
          {
              throw new NotImplementedException(operationContext.IncomingMessageHeaders.Action);
          }
          return bookmark;
      }
  }
  
  //ServiceContract exposed on the endpoint
  [ServiceContract(Name = "IWorkflowCreation")]
  public interface IWorkflowCreation
  {
      [OperationContract(Name = "Create")]
      Guid Create(IDictionary&lt;string, object&gt; inputs);
  
      [OperationContract(Name = "CreateWithInstanceId", IsOneWay=true)]
      void CreateWithInstanceId(Guid instanceId, IDictionary&lt;string, object&gt; inputs);
  
      [OperationContract(Name = "ResumeBookmark", IsOneWay = true)]
      void ResumeBookmark(Guid instanceId, string bookmarkName, string message);
  
  }
  </code></pre>