Fileless Activation of WCF Service in .NET 4.0

Posted: June 6, 2010 in .NET, WCF
Tags: ,

Every WCF service needs to have a host process.It can be a windows service,IIS or any other .NET program.This host process will create an instance of the System.ServiceModel.ServiceHost class or any custom class deriving from System.ServiceModel.ServiceHostBase.This host class will manage the service configurations, behaviors, channels and make it accessible to the outside world.When a service is hosted in IIS it behaves a little bit differently.Here we need to create a physical file with .svc extension in the virtual directory of the web server.This file actually points to the service class implementing the ServiceContract and System.ServiceModel.Activation.ServiceHostFactory or a derived class System.ServiceModel.Activation.ServiceHostFactoryBase.When IIS receives a request with that .svc file in URI the corresponding ServiceHostFactory creates an instance of the ServiceHost.The markup contained in a .svc file is shown below:

<%@ ServiceHost Language="C#" Debug="true" Factory="System.ServiceModel.Activation.ServiceHostFactory" Service="ServiceRouting.TestService" CodeBehind="TestService.svc.cs" %>

In WCF 4.0 we can create and deploy services in IIS without a physical file in the virtual directory.This can be done using the serviceActivations configuration in the system.serviceModel configuration in web.config as shown below.

<serviceHostingEnvironment >
  <serviceActivations>
    <add factory="System.ServiceModel.Activation.ServiceHostFactory" relativeAddress="./Test.svc" service="ServiceRouting.TestService"/>
  </serviceActivations>
</serviceHostingEnvironment> 

There is no physical file named Test.svc but still I am able to access the service at http://localhost:1182/Test.svc. This is the new Fileless Activation feature introduced in .NET 4.0.

Here we can see that in the relative address we still have to use an extension (here I have used the good old .svc).Going by the design philosophy of REST I will prefer to have the URI as http://localhost:1182/Test .So what happens if I change the relativeAddress attribute to “./Test”.We will get the exception as shown below:

The registered relativeAddress ‘./Test’ under section ‘system.serviceModel/serviceHostingEnvironment/serviceActivations’ in configuration file does not have an extension.

This can be done in a different way using the ASP.NET Routing features provided by the classes in System.Web.Routing namespace.This routing feature was initially introduced with ASP.NET MVC and later was extended to support ASP.NET WebForms as well.Now in .NET 4.0 we have the System.ServiceModel.Activation.ServiceRoute class which allows us to integrate this routing feature with IIS hosted WCF services.To enable this feature we need to do the following:

  • Add module and handler reference as shown below:
    • IIS 6.0
    • <httpModules>
                              <add name="UrlRoutingModule" type="System.Web.Routing.UrlRoutingModule, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
       </httpModules> 
      
    • II7.0
    • <system.webServer>
        <modules runAllManagedModulesForAllRequests="true">
          <add name="UrlRoutingModule" type="System.Web.Routing.UrlRoutingModule, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
        </modules> 
      
        <handlers>
          <add name="UrlRoutingHandler" preCondition="integratedMode" verb="*" path="UrlRouting.axd"/>
        </handlers> 
      
      </system.webServer>
      
      
  • Enable ASP.NET Compatibility mode by adding the aspNetCompatibilityEnabled attribute in web.config as shown below.
  • <serviceHostingEnvironment aspNetCompatibilityEnabled="true" / >
    
    
  • Add the AspNetCompatibilityRequirements attribute in the service class as shown below:
  •     [AspNetCompatibilityRequirements(RequirementsMode=AspNetCompatibilityRequirementsMode.Allowed)]
        public class TestService : ITestService
        {
            ///.................
        }
    
  • Register the routes in Application_Start event in the Global.asax.cs file as shown below:
RouteTable.Routes.Add(new ServiceRoute("test", new ServiceHostFactory(), typeof(TestService)));

The constructor of ServiceRoute class accepts three parameters:

  • Url Prefix or pattern
  • An instance of ServiceHostFactoryBase class or it’s sub classes.
  • The type of the class implementing the Service.

It stores this information in an internal cache and uses it later for service activation.

Now we can access the service as http://localhost:1182/test

Comments
  1. Fileless Activation of WCF Service in .NET 4.0 « Sankarsan’s Journal…

    Thank you for submitting this cool story – Trackback from DotNetShoutout…

  2. Fileless Activation of WCF Service in .NET 4.0 « Sankarsan’s Journal…

    Thank you for submitting this cool story – Trackback from PimpThisBlog.com…

  3. Fileless Activation of WCF Service in .NET 4.0 « Sankarsan’s Journal…

    Thank you for submitting this cool story – Trackback from Servefault.com…

  4. Shaunak says:

    Very informative… Thanx for sharing!

  5. […] This post was mentioned on Twitter by planetcall, Sankarsan Bose. Sankarsan Bose said: Finished my blog post…Fileless Activation of WCF Service in .NET 4.0…http://bit.ly/alYu7g […]

  6. pdog says:

    In the svc file you have Debug=”true”, how do you enable this in file-less activation? my breakpoints don’t hit when debugging once I switched.

  7. Chuck Wagner says:

    SanKarasan,

    Thank you for this post. I was having issues configuring my serviceHostingEnvironment elements to work with my custom Ioc ServiceHostFactory implementation until I ran across your write-up.

    Also, thank you for the information about the System.ServiceModel.Activation.ServiceRoute . I’ve done ASP.NET MVC apps in the past and wasn’t aware that routing features had been add to the Web Forms arena.

    Cheers!

  8. Leonardo says:

    Hi, I tried this but after deploying on IIS the service is not being activated. If I remove AspNetCompatibilityRequirements it works. Do you have any idea of why this could be happening?
    Thanks.

  9. The above post is slightly inaccurate.

    You MUST leave the .svc in the relativeAddress attribute like:

    ONLY THEN will your service be accessible via the extensionless URL http://localhost:1182/test

  10. Sorry the above comment had the XML config stripped out rather than HTML encoded…

    ensure you leave the .svc extension in the add factory section:

    add factory=”System.ServiceModel.Activation.ServiceHostFactory” relativeAddress=”./Test.svc” service=”ServiceRouting.TestService”

  11. Jack says:

    Thank you very much…

    I was able to create a WCF Web Service running under IIS7 from a plan cs class without using a interface and without a svc file. No addresses in web.config at all, everything is relative to the website it is hosted in, making deployment simple.

    The URI example: http://www.MyDomain.com/MyService/GetCustomers

  12. Nishith says:

    SanKarasan, thanks for this post.Its very helpful.But whats the benefit of the fileless activation since we are hosting web directory to IIS. Just only not contains the .svc file.Even we have [servicecontract] attribut to the interface.

    • Bon says:

      One great benefit of this is that you can develop your service code in separate assemblies and not require a .svc file to be created to refer to the assembly.

      This is very useful if you have reusable server code that you want to distribute via NuGet.

  13. Stella Kveen says:

    But a smiling visitant here to share the love (:, btw great design and style .

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.