By   February 21, 2014

Web application developper usually put initialization codes in Global.Application_Start method, which is called when the web application receives the first HTTP request.

But if the application contains a WCF service who expose an non-HTTP endpoint (ex: net.tcp), Application_Start may not be called before a non-HTTP request is processed.

How to ensure that an application is initialized correctly before processing any HTTP or non-HTTP request? Here is a solution:

  1. Create a static class who manage application initialization/finilization
    
    using System;
    
    namespace MyWebApplication
    {
        public static class AppManager
        {
            private static object _locker = new object();
            private static bool _isInitialized = false;
            private static bool _isFinalized = false;
    
            public static void Initialize()
            {
                // Ensure that initialization is executed only once
                lock (_locker)
                {
                    if (_isInitialized)
                        return;
                    _isInitialized = true;
                }
    
                // Put initialization code here...
            }
    
            public static void Finalize()
            {
                lock (_locker)
                {
                    if (!_isInitialized || _isFinalized)
                        return;
                    _isFinalized = true;
                }
    
                // Put finalization codes here...
            }
        }
    }
    
    
  2. Call Initialize() and Finalize() in Global.asax.cs
    
    using System;
    
    namespace MyWebApplication
    {
        public class Global : System.Web.HttpApplication
        {
            protected void Application_Start(object sender, EventArgs e)
            {
                AppManager.Initialize();
            }
    
            protected void Application_End(object sender, EventArgs e)
            {
                AppManager.Finalize();
            }
        }
    }
    
    
  3. Create a custom service host factory who creates WCF service host with “Opened” and “Closed” events.
    
    using System;
    using System.ServiceModel.Activation;
    
    namespace MyWebApplication
    {
        public class MyServiceHostFactory : ServiceHostFactory
        {
            protected override System.ServiceModel.ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
            {
                var host = base.CreateServiceHost(serviceType, baseAddresses);
                host.Opened += host_Opened;
                host.Closed += host_Closed;
                return host;
            }
    
            private void host_Opened(object sender, EventArgs e)
            {
                AppManager.Initialize();
            }
    
            private void host_Closed(object sender, EventArgs e)
            {
                AppManager.Finalize();
            }
        }
    }
    
    
  4. Modify the markup of *.svc file by specifying the custom factory
    
    <%@ ServiceHost Language="C#" Debug="true" Service="MyWebApplication.Service" CodeBehind="Service.svc.cs" 
        Factory="MyWebApplication.MyServiceHostFactory" %>
    
    

Leave a Reply

Your email address will not be published. Required fields are marked *