Have you ever come across the following error:
“Cross-origin Request Blocked. The same origin policy disallows reading the resource”.
Us to! It turns out, we get this error due to lack of CORS support while sharing resources. When we try to consume the Web API from origin A in a web application residing in origin B, we get the above error. To solve this error, we need to have a good understanding of CORS.
Although the purpose of this article is to learn the practical implementation of enabling CORS in the ASP.NET Web API, we will give a fair amount of weight to the theoretical concept also. CORS stands for Cross-Origin Resource-Sharing. For various security reasons user agents cannot share resources if they are not from the same origin. Various examples of user agents are browsers, HTML documents, scripts, and XMLHttpRequest.
Let us try to understand the concepts of Cross-Origin and Same-Origin. The concept of Origin was described by RF 6454. Two URLs would be called of the same origin, if they have:
1. Scheme (http)
2. Host (server)
3. Port (8888)
The Origin consists of the Scheme, Host, and the Port number.
If two resources have the same combination of scheme, host, and port then they are considered of the same origin, else of the cross origin. Let us consider the following two URI
http://abc.com:80 and http://xyz.com:8080 are not of the same origin since their host and port are not the same. For the security reason resource sharing between these two URL may be restricted. Let us try to understand CORS with the example of XMLHttpRequest. We use the XMLHttpRequest to perform the HTTP operation on the server from the HTML document. There are two URLs used in the XMLHttpRequest:
1. Requested URL or URL of the server
2. URL of the document which initiated the request
If both URLs have the same scheme, host, and port then XMLHttpRequest object will perform the operation else it will block the HTTP operation for security reasons.
Both the server and the browser must have the support of the CORS. By default all recent browsers have CORS support, but as an API developer we need to enable support of CORS in the Web API.
CORS in ASP.NET Web API
Here we have created a very simple ASP.NET Web API which returns an array of classes as shown in the image below:
As you can see that Web API is running on port 8458. Next we are trying to get the data in a JavaScript application which is running on the URI with the port 5901:
In the HTML document we are using an XMLHttpRequest object to make the HTTP call. As it is evident that URI of Web API (URI of the resource requested) and the HTML document (URL from which the request originated) are not the same hence XMLHttpRequest object is blocking the resource sharing since they are not of the same origin. Very likely in the browser we will get the exception as shown in the image below:
Let us dig further into the bug. In the browser, open the developer tool and the network tab. You will find Origin and Host in Request Header as shown in the image below. It is clear that both are not the same, and CORS is not allowed by the user agent XMLHttpRequest.
If you look at the Response Header there would be no information about Access-Control-Allow-Origin.
Since the server does not send a response about which origin can access the resource in the header, XMLHttpRequest object blocks the resource sharing in the browser. Let us go ahead and enable the CORS support for the Web API.
Enabling CORS in ASP.NET Web API
To enable CORS in ASP.NET Web API 2.0, first you need to add the Microsoft.AspNet.WebApi.Cors package to the project. Either you can choose the command prompt to install the package or NuGet manager to search and install as shown in the image below:
You can configure CORS support for the Web API at three levels:
1. At the Global level
2. At the Controller level
3. At the Action level
To configure CORS support at the global level, first install the CORS package and then open WebApiConfig.cs file from App_Start folder.
var cors = newEnableCorsAttribute("http://localhost:5901", "*", "*");
config.EnableCors(cors);
After enabling CORS at the global level, again host the Web API and examine the request and response header. Also notice that in the Enable CORS attribute we have set the Origin URL to the URL of the JavaScript App.
The Web API server is adding an extra header Access-Control-Allow-Origin in the response header as shown in the image below. The URL in the Access-Control-Allow-Origin header in the response header and the URL in the Origin header in the request header must be same then only XMLHttpRequest will allow the CORS operations. In some cases the value of the Access-Control-Allow-Orgin response header will be set to a wild card character*. This means the server allows CORS support for all the origins instead of a particular origin.
We have enabled the CORS support on the server, so we should not get the exception and data should be fetched in the browser.
As we discussed earlier, in the ASP.NET Web API, CORS support can be enabled at three different levels:
1. At the Action level
2. At the Controller level
3. At the Global level
Enable CORS at the Action level
CORS support can be enabled at the action level as shown in the listing below:
[EnableCors(origins: "http://localhost:5901", headers: "*", methods: "*")]
publicHttpResponseMessage GetItem(int id)
{
// Code here
}
In the above code listing we have enabled CORS for the GetItem action. Also we are setting parameters to allow all the headers and support all the HTTP methods by setting value to star.
Enable CORS at the Controller level
CORS support can be enabled at the controller level as shown in the listing below:
[EnableCors(origins: "http://localhost:5901", headers: "*", methods: "*")]
publicclassClassesController : ApiController
{
In the above code listing we have enabled CORS for the Classes Controller. We are also setting parameters to allow all the headers and support all the HTTP methods by setting value to star. We can exclude one of the actions from CORS support using the [DisableCors] attribute.
Enable CORS at the Global level
To configure CORS support at the global level, first install the CORS package and then open the WebApiConfig.cs file from App_Start folder.
var cors = newEnableCorsAttribute("http://localhost:5901", "*", "*");
config.EnableCors(cors);
If you set the attribute in more than one scope, the order of precedence is as follows:
Attributes of EnableCors
There are three attributes pass to EnableCors:
1. Origins: You can set more than one origins value separated by commas. If you want any origin to make AJAX request to the API then set origin value to wild card value star.
2. Request Headers: The Request header parameter specifies which Request headers are allowed. To allow any header set value to *
3. HTTP Methods: The methods parameter specifies which HTTP methods are allowed to access the resource. To allow all methods, use the wildcard value “*”. Otherwise set comma separated method name to allow set of methods to access the resources.
Putting that all together, you can enable CORS for two origins, for all the headers, and then post and get operations as shown in the listing below:
[EnableCors(origins: "http://localhost:5901,http://localhost:8768", headers: "*", methods: "post,get")]
publicclassClassesController : ApiController
{
Optionally you can also pass credentials to the Web API and create a custom policy, but I hope you found this post about the basics of CORS in the ASP.NET Web API. Have something to add? Share your comments below!