2011-06-23

Supporting Cross Origin Resource Sharing (CORS) requests in a WCF Rest service - Part I

If you use try to consume a rest service using JavaScript (jquery) and are using chrome or Firefox (newer versions) you might run into cross domain issues that involves the w3c standard for accessing resources on other domains (or ports).

In short, if you try to request a resource on a page using javascript(call a rest service) that is located on another domain/port then the XMLHttpRequest object that is implemented in the browser will first try to discover if the cross-origin resource is prepared/allows to accept requests from the origin. If this preflight request succeeds then the real request will be fired.
All this is handled by the browsers XMLHttpRequest object so from the JavaScript side this don't affect the code.

The server side code must support cors though.

An example: we take a simple service method that only returns a string.

public string Hello() {
return "Hello!";
}

If we want to allow cors requests, then we must detect the preflight request and reply accordingly and if it is the real request we should perform the actual method.

public string Hello(){
//for all cors requests
WebOperationContext.Current.OutgoingResponse.Headers
.Add("Access-Control-Allow-Origin","*");
//identify preflight request and add extra headers
if (WebOperationContext.Current.IncomingRequest.Method == "OPTIONS") {
WebOperationContext.Current.OutgoingResponse.Headers
.Add("Access-Control-Allow-Methods", "POST, OPTIONS, GET");
WebOperationContext.Current.OutgoingResponse.Headers
.Add("Access-Control-Allow-Headers",
"Content-Type, Accept, Authorization, x-requested-with");
return null;
}
return "Hello!";
}

Basically we first add the Access-Control-Allow-Origin header telling that we allow any origins (we can also specify an origin that matches the origin that the request comes from). Then we check if the request is a preflight request (method is OPTIONS). If it is we add extra headers to declare which methods and headers that we allow the real request to contain. There are a few more access-control headers that we can add if we need and these are described in the w3c spec.

To add this code in every method is not a great solution but in part 2 we will see how we can use WCF extensibility to do this in a more elegant way.

3 comments:

  1. Excellent Post that saved by a lot of time.
    Thanks

    Mark O'Donovan

    http://practical-qlikview.com

    ReplyDelete
  2. awesome :). This post fixed my problem.

    ReplyDelete
  3. Thank you so much for this post. It was just what I needed.

    ReplyDelete