Cross-Domain With WebAPI

Someday, there will rise a need to develop APIs that can be comsumed by multiple clients i.e. cross-domain requests; for example, APIs to be consumed by browser-based client applications e.g. Chrome Extension or an Angular app.

What is Cross-Domain?

Cross-Domain HTTP requests are HTTP requests for resources from a different domain than the domain of the resource making the request. [1]

and this is a big deal because cross-domain requests are subjected to a browsers' same-origin policy:

The same-origin policy means that your JavaScript can only make AJAX calls back to the same origin of the containing Web page (where “origin” is defined as the combination of host name, protocol and port number). [2]

Then there was CORS:

Cross-origin resource sharing (CORS) is a World Wide Web Consortium (W3C) specification that lets JavaScript overcome the same-origin policy security restriction imposed by browsers.

So, now what happens is that when a browser sees that a cross-domain request is about to happen it will send in additional headers (depending on the type of CORS request) with the request for the server to determine whether the requesting origin has access to it. There are 2 kinds of CORS request: Simple and Preflight.

Simple CORS Request

Simple CORS request are when the browser just adds an origin header with the request to identify the requester. If the browser sends a response with the header Allow-Control-Allow-Origin and its value set as * (meaning any origin) or at least the origin value that was sent with the request then it is successful and the requesting data will be present else error. To summarise following conditions are to be met for a request for a simple cors request:

  • GET, HEAD or POST
  • POST’s Content-Type set as one of application/x-www-form-urlencoded, multipart/form-data, or text/plain
  • No custom headers

Preflight CORS Request

Applicable when conditions for a Simple CORS request are not met. Preflight CORS requests consist of an additional prior request using OPTIONS method to the server to get access permission before the actual request takes place. So, 2 requests per cross-domain request or each URL.

Microsoft.AspNet.WebApi.Cors

As you might have guessed from the sub-title above, it is a CORS framework for WebAPI widely available through NuGet to be referenced in your WebAPI application. It is as easy as enabling it on your WebApiConfig.cs file:

public static class WebApiConfig
{
  public static void Register(HttpConfiguration config)
  {
    // Enable Cors
    config.EnableCors();

    //...Routes
  }
}

Then decorate whatever controller which you want Cors support like below with whatever config you prefer. The following allows cors for all origins, headers and methods:

[EnableCors(origins: "*", headers: "*", methods: "*")]
public class TestController : ApiController 
{
    [HttpPost]
    public HttpResponseMessage Post()
    { }
}

More info can be found here on how to fully use this tool.

So, you have no worries about making your APIs cross-domain compliant now and have more control over accessibility. But few things to watch out like when making a PUT or DELETE request which is eligible for a Preflight CORS request and uses OPTIONS method (recall from earlier), you might have your controller set to accept only obvious HTTP methods like POST or GET which will fail the request because you had not allowed OPTIONS to get through.

This post is a summary of my learnings when I was stuck with handling cross-domain request (Preflight) in WebAPI. Hope it will help someone and comment below for any help.