CORS in Web API 2


In my previous article, we discussed about the concept of Route and RoutePrefix, which was introduced as a new feature in WebApi2. Continuing on the same lines, we will now discuss about the concept of Cross Origin Resource Sharing or C.O.R.S.

CORS is a concept about permissions to make cross domain ajax calls. Before we move further, let’s understand the concept of cross domain:

Two domains can be called as different domains:

1. When they differ in schemes (i.e. http or https)
2. When they have different port numbers
3. When they have different domains or sub-domains.

In normal scenarios, an ajax call cannot be made to a resource on another domain, until the content-type is set to jsonp. Same is the case when we try to make an ajax call to a webapi in different domain. When you try to make a call to a web api hosted on another domain, than you will get the following error:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:34290/GetString?_=1420815804319. This can be fixed by moving the resource to the same domain or enabling CORS.

In order to enable cross domain request in webapi, we need to add the reference to the Microsoft ASP.Net Web API 2.2 Cross-Origin Support libraries, apart from the basic webapi libraries.

CORS in WebAPI 2

Next, in order to test this implementation, we will create a new WebApiController (in an MVC application) and a client application with an HTML page, which will send requests to this webapi. To start with, we will first try to see the issue in making cross domain ajax calls in webapi. Than we will enable the CORS feature and see the results. So let’s start by creating a webapi controller.

CORS in WebAPI 2

Next, we remove all the methods in the default api controller and add a simple method GetString, which returns a string.

CORS in WebAPI 2

Run the MVC application. This will result in hosting of the webapi on the same local development port, as the normal mvc application. Now, we add a client application and make an ajax request to the webapi url. So our code becomes:

CORS in WebAPI 2

Run the client application and also open the browser console and see the message we receive.

CORS in WebAPI 2This is the message that we discussed above in the start. An important point to note here is that your request will be hit to the web api. If you add a break-point on the webapi method it will be hit. But the response is blocked by the browser, as per the CORS policy.

In order to enable the cross domain request, we add the following code in the Register method of the WebAPIConfig.cs file.

 config.EnableCors(new EnableCorsAttribute("*", "*", "GET"));

Let’s first test the request and see the results. Than we will discuss what exactly this function does. So send the client request again and see the results.

CORS in WebAPI 2

So now we can see the results. Remember, the request gets sent and hits the api even without enabling this feature, but the issue is, we cannot see the results until this feature is enabled. So let’s discuss the statement that enabled this feature.

To start with the, config.EnableCors enables the api to receive the requests from other domains. We can do this at controller action level, entire controller level or globally on all the controllers.

EnableCors() overload with no parameter:

When we pass no parameter to this function, than we must add [EnableCorsattribute explicitily, on the api action, on which we would like to allow the cross domain requests. Simply adding the config.EnableCors at the WebApiConfig.cs level will not work.

We can also set this attribute on the controller level. In such a case, we expose all the methods of the controller to the ajax requests from outside its domains. So what if you need to disable this for one of controller method. In that case, add [DisableCors] attribute on that method.

When we enable this feature using the [EnableCors] at the controller or action level, we also need to set certain parameters, which include:

1. origins: Specifies the url from which we want to get cross domain requests. Can add multiple values in comma separated format.
2. headers: Specifies the author request headers allowed
3. methods: Specifies the type of request i.e. GET, POST, PUT etc, which should be enabled on this method.

See the code below, we enable the CORS feature in WebApiConfig.cs with no parameter and add the [EnableCors] parameter at the action level.

CORS in WebAPI 2

EnableCors() overload with parameter:

This is the version of the function which we used earlier in the start of the discussion. This will enable the cross domain access at the global level i.e. on all the api controllers, until we apply [DisableCors] attribute explicitly on the controller actions. So let’s add these settings at global level.

CORS in WebAPI 2

Here, the use of “*” means ALL, i.e. all origins types are allowed to make requests to this api, all the header types are allowed and GET request types from another domain are allowed.

Let’s test the code with [DisableCors]  attribute and global configuration to enable cross domain requests. So our code becomes:

CORS in WebAPI 2

As we have disabled the request for the method named GetSecondString(), it again results in error related to cross domain policy for this method. However, call to the method GetFirstString() works as expected. See the results for request to the second method:

CORS in WebAPI 2

And, the request for the first method works fine.

CORS in WebAPI 2

One very interesting issue you might face is that when you omit the {action} parameter in the routing template, it will cause issues, to have two or methods, with same signature and having the same type i.e. GET, POST etc. For ex, when you have two GET methods, named FindProduct and GetProduct, both taking a single input parameter of type int, than you will get the issue

"Multiple actions were found that match the request: FindProduct on type WebAPI.Controllers.ProductsControllerGetProduct on type ProductsController"

The reason being that when the action name is not specified, than it will have two methods of the same type GET. mapping to same type of parameters, and it will not be able to identify which method to be invoked. Change the signature of one of the methods, and it will work.

So this was about the feature of cross origin resource sharing in webapi.

Advertisements

About Jasminder

.Net developer and blogger by profession, keen to learn new technologies, love nature, music and cricket.
This entry was posted in ASP.Net web API and tagged . Bookmark the permalink.

I have a suggestion..

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s