WF 4.0: How to automatically start a workflow by itself hosted in AppFabric

Hello,

In my current project we want to simulate the windows services behaviour using workflow foundation 4.0 and AppFabric. This can not be achieved out of the box, so a little trick is needed. At the beginning I tried to use Global.asax, but that is not a good idea because it is only executed for http requests. So I tried another approach and this one was good.

  1. Let’s start with a WCF Workflow Service application.
  2. Add a folder called App_Code. This will contain code that will be compiled at run time.
  3. Create a proxy to the service in the project using wcf service reference. It is quite weird but necessary in order to make that first call that will launch our service.
  4. In the config you need to put the namespace of the service client before the contract interface name (ProxyFakeService.IService).
      <endpoint address="net.pipe://localhost/SelfInitializingWF/Service1.xamlx" binding="netNamedPipeBinding" bindingConfiguration="NetNamedPipeBinding_IService" contract="ProxyFakeService.IService" name="NetNamedPipeBinding_IService">
            <identity>
              <servicePrincipalName value="host/localhost" />
            </identity>
          </endpoint>
    
  5. You need a class in the App_Code folder that will be invoked when the application pool recycles or starts. IIS will automatically execute the AppInitialize() method of that class. This one is a singleton and calls the service in another thread, so IIS will be able to initialize the service while the singleton invokes it. If you don’t do that the call will return a timeout because that call is blocking the service initialization. The invocation is using a channelfactory because in a WF project VS doesn’t creates a normal wcf client, it creates activities for the workflow.
    /// <summary>
        /// This class is used to make the first call when the app pool starts (o recycles).
        /// http://msdn.microsoft.com/en-us/library/system.web.hosting.virtualpathprovider.aspx
        /// </summary>
        public class AutoStartCode
        {
            //singleton for keeping the object alive executing the calling.
            private static AutoStartCode instance = new AutoStartCode();
    
            //field with keeps the task out of the method.
            private Task callingTask;
    
            //singleton private constructor
            private AutoStartCode() { }
    
            // iis calls to this method when it starts the apppool
            public static void AppInitialize()
            {
                instance.MakeCallToServiceInParallel();
    
            }
    
            /// <summary>
            /// Launch a task for do the call in parallel. The call must be in parallel in order to not blocking the thread and permit IIS to start the service.
            /// </summary>
            private void MakeCallToServiceInParallel()
            {
                // Do the call in parallel.
                callingTask = Task.Factory.StartNew(() =>
               {
    
                   instance.CallToService();
               });
    
            }
    
            /// <summary>
            /// Calls the WF service.
            /// </summary>
            private void CallToService()
            {
                //use the channelfactory for creating the proxy using the interface of the service reference and the endpoint name.
                var channelFactory = new ChannelFactory<IService>("NetNamedPipeBinding_IService");
    
                try
                {
    
                    //creates the channel
                    var channel = channelFactory.CreateChannel();
    
                    //calls the service
                    var response = channel.GetData(new GetDataRequest() { @int = 2 });
    
                }
                catch
                {
    
                    channelFactory.Abort();
                    throw;
    
                }
                finally
                {
                    //close the channel.
                    channelFactory.Close();
    
                }
            }
        }
    
  6. It is necessary to configure the IIS and AppFabric for enabling the autostart. This is a great link for that. Set the AlwaysRunning mode in the application pool, the net.pipe in the service protocols and of course use the AppFabric configuration for enabling the autostart mode in the service.

All of this fits perfectly with the single instance pattern that I exposed in my last post.

Here is the code.
http://cid-d9a7d79398cdd8ff.office.live.com/embedicon.aspx/P%c3%bablico/blog/SelfInitializingWF.rar

About these ads

3 comments

  1. [...] my current project we need to have just one instance of a wf service in the cluster. That instance should be automatically created, that’s easy calling the receive in the global.asax, here is a good [...]

  2. [...] got some criticism from Alex Golesh in a comment on one of my latest Posts (Managing Silverlight resources contained in external assemblies), First I would like to thank him for taking his time and writing this comment, I would like to [...]

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 155 other followers

%d bloggers like this: