سؤال

Is it possible to define a standard ServiceHostFactory foreach 'workflow' service (xamlx)

Our customers can make there own workflows (xamlx) using a custom workflow designer. We force the workflowservices into having a WS2007FederationHttpBinding with TransportSecurity. We turn of ServiceMetadataBehavior of for the WorkflowService and finally add a DataContractResolver that does some type resolving.

The ServiceHostFactory

    public class MyServiceHostFactory : WorkflowServiceHostFactory
{
    protected override WorkflowServiceHost CreateWorkflowServiceHost(
        System.ServiceModel.Activities.WorkflowService service,
        Uri[] baseAddresses)
    {
        WorkflowServiceHost host = base.CreateWorkflowServiceHost(service, baseAddresses);

        foreach (Uri adres in baseAddresses)
        {
            if (adres.Scheme == "https")
            {
                WorkflowCreationEndpoint endpoint = new WorkflowCreationEndpoint(
                    new WS2007FederationHttpBinding("IWorkflowService_ws2007FederationHttpBinding"),
                    new EndpointAddress(adres));

                host.AddServiceEndpoint(endpoint);

                PageflowDataContractResolver.AttachDataContractResolver(endpoint);
            }
        }

        var metadataBehavior = host.Description.Behaviors.Find<ServiceMetadataBehavior>();
        metadataBehavior.HttpGetEnabled = false;

        host.WorkflowExtensions.Add(new WorkflowInstanceTracking());

        return host;
    }

    public override ServiceHostBase CreateServiceHost(string constructorString, Uri[] baseAddresses)
    {
        return base.CreateServiceHost(constructorString, baseAddresses);
    }

    protected override WorkflowServiceHost CreateWorkflowServiceHost(System.Activities.Activity activity, Uri[] baseAddresses)
    {            
        return base.CreateWorkflowServiceHost(activity, baseAddresses);
    }
}

The workflows exist in a database as Ron Jacob wrote in this blog. 'Consultants' and/or end users can create workflows using a custom tool, but each time they do they must not forget to add a serviceActivation element in the web.config which is not wanted.

<system.serviceModel>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="false">
      <baseAddressPrefixFilters>
        <add prefix="http://localhost" />
      </baseAddressPrefixFilters>
      <serviceActivations>
        <add relativeAddress="~/Workflows/test.xamlx" service="Workflows/test.xamlx" factory="Foo.Bar.MyServiceHostFactory" />
      </serviceActivations>
    </serviceHostingEnvironment>
    <protocolMapping>
        <add scheme="https" binding="ws2007FederationHttpBinding" />
    </protocolMapping>
..
هل كانت مفيدة؟

المحلول

I think it would be correct to rephrase your question as:

Is there a way to change the default WorkflowServiceHostFactory for a web application so that config-less xamlx activation will use my WSHF instead.

If I have understood your question correctly then I don't think there is a way to do this. I had a quick look to see if there is a place you can override it but couldn't see any. Another way to achieve this is to modify the web.config as necessary when a user uploads a new workflow. Editing the web.config in-flight should result in any currently running pulses of execution being serviced by the existing AppDomain while a new AppDomain is created to service new requests to the web application. Thus no loss of workflow processing should occur. This of course would require some testing and verification.

UPDATE It looks like this might be possible. If you add the following to your web.config (which is from the default config for workflow activation).

<?xml version="1.0"?>
<configuration>
  <configSections>
    <sectionGroup name="system.xaml.hosting"
                  type="System.Xaml.Hosting.Configuration.XamlHostingSectionGroup,     System.Xaml.Hosting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
      <section name="httpHandlers"
               type="System.Xaml.Hosting.Configuration.XamlHostingSection, System.Xaml.Hosting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
        </sectionGroup>
  </configSections>

  <system.xaml.hosting>
    <httpHandlers>
      <add xamlRootElementType="System.ServiceModel.Activities.WorkflowService, System.ServiceModel.Activities, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
           httpHandlerType="System.ServiceModel.Activities.Activation.ServiceModelActivitiesActivationHandlerAsync, System.ServiceModel.Activation, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
      <add xamlRootElementType="System.Activities.Activity, System.Activities,     Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
           httpHandlerType="System.ServiceModel.Activities.Activation.ServiceModelActivitiesActivationHandlerAsync, System.ServiceModel.Activation, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
    </httpHandlers>
  </system.xaml.hosting>

</configuration>

The class ServiceModelActivitiesActivationHandlerAsync that this default config uses is implemented as follows:

internal class ServiceModelActivitiesActivationHandlerAsync : ServiceHttpHandlerFactory, IServiceModelActivationHandler
{
    // Methods
    public ServiceHostFactoryBase GetFactory()
    {
        return new WorkflowServiceHostFactory();
    }
}

Then instead of using the ServiceModelActivitiesActivationHandlerAsync, provide an implementation yourself which instantiates your own WorkflowServiceHostFactory in the GetFactory method. Update the web.config above to point to your new httpHandlerType and you should be done.

I haven't tested this at all. It's possible IIS will not like the web.config overriding the system.xaml.hosting section.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top