Hosting a HTTP service with ASP.NET-compatible context

ASP.NET provides a powerful platform for developing web applications over the .NET framework. An ASP.NET web application is also a natural hosting environment for a WCF service over the web HTTP protocol, which means developers can deploy WCF services with ASP.NET web pages in the same web application side by side without any particular effort.

However, by default, some ASP.NET runtime features or state objects are not available to WCF service code even if they are within the same web application. Those limited features include:

  • HttpContext is always null when accessed from within a WCF service.
  • Configuration-based URL Authorization (via <authorization> configuration element) is not available to WCF .svc files. These settings are ignored for WCF requests if a service resides in a URL space secured by ASP.NET's URL authorization rules.
  • Custom HttpModules injected into an ASP.NET application to intercept requests at later stages of the pipeline do not intercept WCF requests.
  • ASP.NET-specific states such as sessionState and Application Cache are not available to WCF service codes.

Then, how can we make such features accessible to a WCF service again? Well, the WCF-service hosting infrastructure has provided a feature called ASP.NET Compatibility Mode, which can help resolve the problem. This feature is by default disabled; we will show you how to enable this feature so that the WCF service continues to enjoy the ASP.NET runtime in this recipe.

How to do it...

  1. The first thing we need to do is get an existing ASP.NET web application and then add a new WCF service into the web application. For our sample case, we will use an empty ASP.NET website with two simple ASPX pages as the hosting website. Then, a WCF service named EchoService.svc will be added into it so that the two ASPX web pages can run side by side with the EchoService.svc service. The following screenshot shows the web application structure in Visual Studio Solution Explorer.
    How to do it...

    The EchoService has a very simple ServiceContract, which contains a single Echo operation to return some data of type String (refer to the following code snippet).

    [ServiceContract]
    public interface IEchoService
    {
        [OperationContract]
        string Echo();
    }
  2. Now we have the ASP.NET web pages and WCF service hosting together. However, the WCF service code still cannot access those ASP.NET-specific runtime objects yet. What we need to do is apply ASP.NET Compatibility Mode into the hosting web application and the WCF service deployed in it.

    To enable ASP.NET Compatibility Mode, we can simply set the aspNetCompatibilityEnabled attribute to true in the <serviceHostingEnvironment> setting of the WCF configuration section. The following screenshot shows the configuration fragment with ASP.NET Compatibility Mode enabled.

    How to do it...

    On the service implementation class of the WCF service, we need to apply the System.ServiceModel.Activation.AspNetCompatibilityRequirements attribute and set the RequirementsMode property to AspNetCompatibilityRequirementsMode.Allowed. This is quite useful, since sometimes we might not want certain WCF services to gain access to those ASP.NET runtime context objects, even if the hosting web application has ASP.NET Compatibility Mode enabled. The following code snippet shows the implementation class of the sample EchoService, which has applied the proper AspNetCompatibilityRequirements setting:

    using System.ServiceModel.Activation;
    
    [AspNetCompatibilityRequirements(
        RequirementsMode=AspNetCompatibilityRequirementsMode.Allowed
        )]
    public class EchoService : IEchoService
    {
    …
    }
  3. Having all the services and applications configured appropriately, we can now start enjoying the ASP.NET context objects within the WCF service code. The following code snippet shows the sample Echo operation code, which collects several runtime properties from the ASP.NET request context and returns them to the service caller:
    public class EchoService : IEchoService
    {
       public string Echo()
       {
        var approot = HttpContext.Current.Server.MapPath("~/");
    
        var data = HttpContext.Current.Cache["key1"];
    
        var url = HttpContext.Current.Request.RawUrl;
            
        return string.Format("{0}, {1}, {2}", approot, data, url) ;
       }
    }

    By performing a quick test on the WCF service in the WCF Test Client tool, we can get the expected response with all the ASP.NET context properties returned, as shown in the following screenshot:

    How to do it...

How it works...

WCF HTTP services hosted in an ASP.NET web application can be run in two different modes—the default mode and ASP.NET Compatibility Mode.

In the default mode, the ASP.NET runtime intercepts the WCF request in the early stage of the pipeline: BeginRequest (one of the interception points of ASP.NET HttpModule), so most of the ASP.NET Context information is not available to the WCF service code. When ASP.NET Compatibility Mode is enabled on the WCF service, the WCF service runtime hooks up into the ASP.NET HTTP pipeline through both module and handler for the HTTP transport, so those ASP.NET-specific context data become available again.

There's more...

For more detailed information about ASP.NET Compatibility Mode for WCF service hosting, you can refer to the following article from Wenlong Dong's Blog:

See also

  • Using the WCF Test Client tool to test a service in Chapter 12
  • Complete source code for this recipe can be found in the \Chapter 3\recipe3\ folder