Code that needs to run before a WCF service is called for the first time

I was looking for a way to execute some piece of code only once when a WCF service is accessed for the first time. In particular, I needed to initialize the Castle IoC container.

The first attempt seemed easy: use the Application_Start event in the global.asax file. While this works, it has a drawback: it only works with http protocol! And I want a solution that works independent from the protocol that is used to access the service.

The next possibility I found was to add a special folder called App_Code, and put a class in it that contains a method AppInitialize. When the service is accessed the first time, the code in this method will be executed first. While this works perfectly, there is one drawback… code in the App_Code folder is not build before being deployed, so you end up with source code on the server, which I think is not optimal.

Luckily there is a clean way to make this work for every protocol, and it’s actually quite simple. First add a class to your service project, for example HostFactory, and put the following method in it:

  1: public class HostFactory : ServiceHostFactoryBase
  2: {
  3:     public override ServiceHostBase CreateServiceHost(string constructorString, Uri[] baseAddresses)
  4:     {
  5:         Type service = Type.GetType(constructorString);
  6:         ServiceHost host = new ServiceHost(service, baseAddresses);
  7:         // hook up event handlers
  8:         host.Opening += new EventHandler(host_Opening);        
  9:         return host;
 10:     }
 11: 
 12:     void host_Opening(object sender, EventArgs e)
 13:     {
 14:         // Code that runs on application startup
 15:         var iocContainer = WindsorBootstrapper.Initialize();
 16:         var locator = new WindsorServiceLocator(iocContainer);
 17:         ServiceLocator.SetLocatorProvider(() => locator);
 18:     }
 19: }

and also, make sure to add Factory to your svc file, like:

  1: <%@ ServiceHost Language="C#" Debug="true" Service="EC.Service.Quartz.ServiceAdapter.QuartzService" 
  2:     CodeBehind="QuartzService.svc.cs" Factory="EC.Service.Quartz.HostFactory" %>

Now you have a protocol-independent way of making sure that code is executed before the first request to the service is done.

August 19, 2010 22:44 by lustuyck
E-mail | Permalink | Comments (0) | Comment RSSRSS comment feed