Tuesday, September 16, 2014

Enable autostart in IIS 7.5 (without AppFabric)

You can create your own autostart provider for your WCF services and there is no need to use AppFabric for autostarting WCF services.

You will need/configure 4 things to enable autostart in WCF
            1) Autostartprovider (source code below)
            2) Add the reference of the above library to your WCF service
            3) Modify the svc file to use factory - 

<%@ ServiceHost Language="C#" Debug="true" Service="Service1" CodeBehind="Service1.svc.cs" Factory="Web.Hosting.ServiceBusHostFactory" %>

            4) Modify the applicationHost.config in C:\Windows\System32\Inetsrv\config in the following places

a) At AppPool level
                       <add name="AutoStartSite" managedRuntimeVersion="v4.0" autoStart="true" startMode="AlwaysRunning"  />



b) At Site level -
                      <site name="AutoStartSite" id="2" serverAutoStart="true">


c) At Virtual directory/Application level
                      <application path="/AutoStartVD" applicationPool="AutoStartSite" serviceAutoStartEnabled="true" serviceAutoStartProvider="MyAutoStartProvider">


d) serviceAutoStartProviders itself -
                       
In your applicationHost config file between <webLimits/> and    </system.applicationHost>, add the following section - 

         <serviceAutoStartProviders>
            <add name="MyAutoStartProvider" type="Web.Hosting.AutoStartProvider, Web.Hosting" />
        </serviceAutoStartProviders>



Thats it. Deploy your WCF service. Fire up DbgView.exe for debugging purposes as there are some diagnostics statements in the AutoStartProvider.




================START Autostartprovider source code=======================

File::::AutoStartProvider.cs

using System;
using System.Diagnostics;
using System.IO;
using System.ServiceModel;
using System.Threading;
using System.Web.Hosting;


namespace Web.Hosting
{
    public class AutoStartProvider : IProcessHostPreloadClient
    {
        
        public void Preload(string[] parameters)
        {
            bool isServceActivated = false;
            int attempts = 0;
            while (!isServceActivated && (attempts < 10))
            {
                Thread.Sleep(1 * 1000);
                try
                {
                    if (!System.Web.Hosting.HostingEnvironment.IsHosted) 
                        return;

                    var virtualPath = HostingEnvironment.ApplicationVirtualPath;
                    var physicalPath = HostingEnvironment.ApplicationPhysicalPath;
                    var svcFiles = Directory.GetFiles(physicalPath, "*.svc");

                    foreach (string svcFile in svcFiles)
                    {
                        ServiceHostingEnvironment.EnsureServiceAvailable(virtualPath + "/" + Path.GetFileName(svcFile));
                    }

                    isServceActivated = true;
                    System.Diagnostics.Trace.WriteLine(String.Format("Activated {0}", virtualPath));
                }
                catch (Exception exception)
                {
                    attempts++;
                    //continue on these exceptions, otherwise fail fast
                    if (exception is EndpointNotFoundException
                        || exception is ServiceActivationException
                        || exception is ArgumentException)
                    {
                        System.Diagnostics.Trace.WriteLine(exception.Message);
                    }
                    else
                    {
                        throw;
                    }
                }
            }
        }
    }

}

-------------------------------------------------------------------------------------------------------------

File::::ServiceBusHostFactory.cs

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.Text;
using System.Threading.Tasks;

namespace Web.Hosting
{
    public class ServiceBusHostFactory : ServiceHostFactory
    {
    Type incomingServiceType;
    Uri[] incomingBaseAddresses;
    /// <summary>
    /// Reopen Service host on network intermittent error
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void OnServiceHostFaulted(object sender, EventArgs e)
    {
        ICommunicationObject faultedHost = (ICommunicationObject) sender;
        faultedHost.Abort();
        //Log failure
        bool IsSourceExist = EventLog.SourceExists(CustomEventLogInstaller.EventSourceName);
        if (IsSourceExist)
            EventLog.WriteEntry(CustomEventLogInstaller.EventSourceName,
                String.Format("Host {0} connection failed at address {1}",this.incomingServiceType.ToString(),
                        this.incomingBaseAddresses.FirstOrDefault()), EventLogEntryType.Error);
        ServiceHost host =  base.CreateServiceHost(this.incomingServiceType, this.incomingBaseAddresses);       
        host.Faulted += this.OnServiceHostFaulted;
        System.Threading.Thread.Sleep(TimeSpan.FromSeconds(10)); // Sleeping here just to allow some time for the resource to come back.
        host.Open();
        //log host reopened
        if (IsSourceExist)
            EventLog.WriteEntry(CustomEventLogInstaller.EventSourceName,
                String.Format("Service bus connection reopened for {0}", this.incomingBaseAddresses.FirstOrDefault()), EventLogEntryType.Information);
    }

    protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
    {
    this.incomingServiceType = serviceType;
    this.incomingBaseAddresses = baseAddresses;
    ServiceHost host = base.CreateServiceHost(this.incomingServiceType, this.incomingBaseAddresses);
    host.Faulted += this.OnServiceHostFaulted;
    return host;
    }
 }

}

================END Autostartprovider source code=======================

No comments:

Post a Comment