WCF REST API CORS Support Via WCF Behavior Extension

The REST APIs are designed to work with Web i.e. a network of different connected  domain that works together by sharing resources. But in today’s world we have all modern browsers which are highly supporting the CORS. Those who don’t know about CORS can learn about it here.

In a simple language, CORS is simply allowing other domain to request for a resource hosted in a another domain. So, for example, if an image is hosted on SiteA.com and SiteB.com wants to access this image to display in one of his page, then SiteA.com has to allow it. The browser which is accessing SiteB.com will know by reading the response header which are coming after making a request to SiteA.com. So if it has CORS header information then the request can be fetched otherwise browser will simply reject the response without displaying any specific error.

Sample Response headers of CORS from SiteA.com:

  • Access-Control-Allow-Origin: http://SiteB.example
  • Access-Control-Allow-Methods: POST, GET, OPTIONS
  • Access-Control-Allow-Headers: X-PINGOTHER
  • Access-Control-Max-Age: 1728000

You visualize the above situation something like below though it’s not a complete coverage of whole CORS concept but it will get you going.

browser reject the response

browser accepts the response

Know more about the Server side CORS and Client CORS. The same scenario applies when a cross domain REST API request is made. So your WCF REST API service should serve the response with CORS headers. The feature is not supported out of box but WCF provides a lot of extensibility points. So you can extend/create a new behavior and plug it in to have your WCF REST API CORS enabled.

So conceptually you can develop a new Endpoint behavior Endpoint behavior with a custom message inspector message inspector that will inject the CORS headers settings in the response your requesting browser doesn’t deny it.

Here’s how the custom message inspector would look like the following:
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.ServiceModel.Channels;  
  5. using System.ServiceModel.Dispatcher;  
  6. using System.Text;  
  7. using System.Threading.Tasks;  
  8.    
  9. namespace WebHttpBehaviorExtensions.Cors  
  10. {  
  11.     public class CustomHeaderMessageInspector : IDispatchMessageInspector  
  12.     {  
  13.         Dictionary<stringstring> requiredHeaders;  
  14.         public CustomHeaderMessageInspector(Dictionary<stringstring> headers)  
  15.         {  
  16.             requiredHeaders = headers ?? new Dictionary<stringstring>();  
  17.         }  
  18.    
  19.         public object AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel, System.ServiceModel.InstanceContext instanceContext)  
  20.         {  
  21.             return null;  
  22.         }  
  23.    
  24.         public void BeforeSendReply(ref System.ServiceModel.Channels.Message reply, object correlationState)  
  25.         {  
  26.             var httpHeader = reply.Properties["httpResponse"as HttpResponseMessageProperty;  
  27.             foreach (var item in requiredHeaders)  
  28.             {  
  29.                 httpHeader.Headers.Add(item.Key, item.Value);  
  30.             }  
  31.         }  
  32.     }  
  33. }  
Message inspector is actually that adds the headers into response with method BeforeSendReply. Now we have to inject this custom message inspector object into collection of default message inspector. To do that we have created a new class implementing IEndpointBehavior interface, also we will be using the same class to extend the base class BehaviorExtensionElement (This would help injecting the behavior from configuration.).
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.ServiceModel.Configuration;  
  4. using System.ServiceModel.Description;  
  5.    
  6. namespace WebHttpBehaviorExtensions.Cors  
  7. {  
  8.     class EnableCorsBehavior : BehaviorExtensionElement, IEndpointBehavior  
  9.     {  
  10.         public void AddBindingParameters(ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)  
  11.         { }  
  12.    
  13.         public void ApplyClientBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime)  
  14.         { }  
  15.    
  16.         public void ApplyDispatchBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher)  
  17.         {  
  18.             var requiredHeaders = new Dictionary<stringstring>();  
  19.    
  20.             requiredHeaders.Add("Access-Control-Allow-Origin""*");  
  21.             requiredHeaders.Add("Access-Control-Request-Method""POST,GET,PUT,DELETE,OPTIONS");  
  22.             requiredHeaders.Add("Access-Control-Allow-Headers""X-Requested-With,Content-Type");  
  23.    
  24.             endpointDispatcher.DispatchRuntime.MessageInspectors.Add(new CustomHeaderMessageInspector(requiredHeaders));  
  25.         }  
  26.    
  27.         public void Validate(ServiceEndpoint endpoint) { }  
  28.    
  29.         public override Type BehaviorType  
  30.         {  
  31.             get { return typeof(EnableCorsBehavior); }  
  32.         }  
  33.    
  34.         protected override object CreateBehavior()  
  35.         {  
  36.             return new EnableCorsBehavior();  
  37.         }  
  38.     }  
  39. }  
That’s it! Now to show you the configuration settings I’ll just put the parts which are needed to be updated with this new behavior setting. In configuration under <service.model> add the following endpoint behavior:

Define the Extension behavior first:
  1. <extensions>  
  2.     <behaviorExtensions>  
  3.       <add name="corsBehavior" type="WebHttpBehaviorExtensions.Cors.EnableCorsBehavior, WebHttpBehaviorExtensions, Version=1.0.0.0, Culture=neutral" />  
  4.     </behaviorExtensions>  
  5. </extensions>  
Add behavior
  1. <behaviors>  
  2.    <endpointBehaviors>  
  3.      <behavior name="webHttpServiceBehavior">  
  4.        <corsBehavior />  
  5.        <webHttp/>  
  6.      </behavior>  
  7.    </endpointBehaviors>  
  8. </behaviors>  
Now add the custom behavior settings to your endpoint in <services> section:
  1. <services>  
  2.    <service name="WcfWebHttpIISHostingSample.TestService" behaviorConfiguration="ServiceBehavior">  
  3.       <endpoint binding="webHttpBinding" contract="WcfWebHttpIISHostingSample.ITestService" behaviorConfiguration="webHttpServiceBehavior" />  
  4.    </service>  
  5. </services>  
That’s it! Now you can test your settings by deploying the WCF REST service to IIS and when making a request press F12 and look for Network request and response Headers. You can also use tools like `Fiddler` and `Chrome Post Master` to perform a Get/Post request and analyzing header.

This blog post is part of an Extension behavior library that I’m currently working on to provide a set of Regularly required feature which aren’t available out of the box. To download the Library via Nuget from here:

Extension behavior library

If you like to contribute or want to look at the source code, the complete source code is open source and hosted on Github.

Github

 

Next Recommended Readings