Using Cross Origin Resource Sharing (CORS) in ASP.NET Web API

Introduction

For security reasons browsers prohibit AJAX calls to resources residing outside the current origin. This means you under the current settings, you can't provide a service exposed by a Web API to some other origin. However, at times you might want to allow a legitimate origin to access a resource. This is where Cross Origin Resource Sharing (CORS) specifications come into the picture.

While there are other ways to enable CORS at the web application level, the ASP.NET Web API takes CORS support a step further through certain attributes. Using these attribute you can fine tune CORS at the global level, controller level or individual action level. This article discusses how this support can be used in your applications.

What is CORS?

As already mentioned, CORS stands for Cross Origin Resource Sharing. CORS is a W3C standard and deals with a mechanism for making AJAX calls across different origins. An origin is a combination of a scheme, host and port. For example, consider the following two URLs:

http://www.website1.com
http://www.website2.com

In these URLs the scheme is http, and the hosts are www.website1.com and www.website2.com respectively. Port number is not mentioned explicitly. In this case since the hosts are different, they are considered as different origins. On the same lines http://www.website1.com and https://www.website1.com are different origins because their schemes are different (http and https).

Suppose that you have developed an ASP.NET Web API and it is hosted at http://www.website1.com. You have also developed a website that is hosted at http://www.website2.com. The website now wants to consume the Web API developed earlier, and you use XMLHttpRequest or jQuery $.ajax() to call the Web API. Unfortunately this communication will fail because the browser won't permit you to make AJAX calls to resources that are not part of the origin under consideration.

While the browser blocks such calls for the sake of security, such calls might be legitimate and you may want this communication to succeed. CORS specification establishes a standard way to allow such communication. Using CORS you can enable cross origin calls so that your web page can make AJAX requests to a Web API hosted in a different origin.

To understand this problem clearly let's try to make such cross origin calls between two different web applications. Begin by creating an ASP.NET Web API project and modify the default ValuesController as shown below:

namespace CORSWebAPIDemo.Controllers
{
    public class ValuesController : ApiController
    {
        public IEnumerable<string> Get()
        {
            return new string[] { "Red", "Green", "Blue" };
        }

    }
}

As you can see the Get() Web API method simply returns an array of strings with three elements - Red, Green and Blue.

Now add an Index view for the HomeController's Index method (Note that you are still inside the Web API project). Write the following code inside the Index view.

<head runat="server">
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
    <script src="../../Scripts/jquery-1.7.1.min.js"></script>


    <script type="text/javascript">
        $(document).ready(function () {
            var options = {};
            options.url = "http://localhost:49250/api/values";
            options.type = "GET";
            options.contentType = "application/json";
            options.success = function (results) {
                alert(results.join());
            };
            options.error = function (evt) {
                alert(evt.status + " - " + evt.statusText);
            };

            $.ajax(options);
        });
    </script>

</head>

The above code essentially makes an $.ajax() call to the Web API you developed earlier. The success method displays the array by joining its element. In this case Index view as well as the Web API belong to the same origin (since they are part of the same project) and hence this call will succeed. You can test this by running the Index view. You should see an alert box as shown below:

CORS Figure 1

If you see the request and response through Chrome Developer Tools (or whatever equivalent provided by your browser) you will observe the following:

CORS Figure 1

As you can see the message is - "XHR finished loading". The $.ajax() of jQuery uses XMLHttpRequest (XHR) behind the scenes and the XHR call is successful as indicated by the message above.

Now, add a new ASP.NET MVC 4 project (Empty template) to the same solution. Add a HomeController and Index view to it and copy-paste the markup of Index view developed earlier (i.e. Index view from Web API project) inside the newly created Index view. In this case you are trying to make an $.ajax() call from a different web application to the Web API. Run the newly created Index view. This time you should see an error as shown below:

CORS Figure 3

As you can see the XMLHttpRequest call has failed and it clearly says that the call is not allowed by "Access-Control-Allow-Origin". What is "Access-Control-Allow-Origin"? It's an HTTP header that tells you whether an another origin can call a resource from the origin under consideration.

Enabling CORS via web.config

Now that you know the problem, let's see how to get rid of the error. A simple way is to add "Access-Control-Allow-Origin" header in the web.config. Open the web.config of Web API project and add the following markup under <system.webServer> section:

<system.webServer>
    <httpProtocol>
      <customHeaders>
        <add name="Access-Control-Allow-Origin" value="*"/>
      </customHeaders>
    </httpProtocol>
<system.webServer>

As you can see the <httpProtocol> section now adds an http header named Access-Control-Allow-Origin and sets its value to * (all origins are allowed). This will enable CORS for the Web API. If you run the application again, this time it won't give any error. 

CORS support in Web API

While the web.config way of enabling CORS works as expected, it offers very little control on what can be shared. It's a global level setting that enables access to all the resources. You may want to control what you are sharing with the outside world. Luckily, ASP.NET Web API intends to provide CORS support through certain attributes. As of this writing the assemblies that provide CORS support in Web API are available as a part of nightly builds. To grab these assemblies you need to add a new Package source in Visual Studio as shown below:

CORS Figure 4

Once you add a new source (http://myget.org/f/aspnetwebstacknightly) you can install the Microsoft ASP.NET Web API Cross Origin Support package.

CORS Figure 5

Installing this package adds reference to two assemblies that are responsible for the CORS support:

  • System.Web.Cors.dll
  • System.Web.Http.Cors.dll

Enabling CORS Support

Now that you have installed the CORS support assemblies, let's enable CORS support. Remember to remove the "Access-Control-Allow-Origin" header from the web.config in case you added as described in the earlier section. Then open the WebApiConfig.cs file from the Web API project (If you can't see this file, go to Global.asax, right click on WebApiConfig from the Application_Start event and select Go to Definition menu option) and modify it as shown below:

namespace CORSWebAPIDemo
{
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );
            config.EnableCors();
        }
    }
}

As you can see EnableCors() method enables CORS support for the Web API. At this point you have not yet specified which of the Web API controllers will support CORS. To do so, go to the ValuesController and decorate the Web API controller class with [EnableCors] attribute as shown below:

namespace CORSWebAPIDemo.Controllers
{
    [EnableCors("*", "*", "*")]
    public class ValuesController : ApiController
    {
        public IEnumerable<string> Get()
        {
            return new string[] { "Red", "Green", "Blue" };
        }

    }
}

As you can see the ValuesController class now has [EnableCors] attribute. The EnableCors attribute takes three parameters viz. origins, headers and methods. A value of * indicates that all origins, headers and methods are allowed. This technique will allow you to call all the methods from the Web API controller. If you wish to expose only certain methods you can individually decorate the methods with the [EnableCors] attribute as shown below:

namespace CORSWebAPIDemo.Controllers
{
    public class ValuesController : ApiController
    {
        [EnableCors("*", "*", "*")]
        public IEnumerable<string> Get()
        {
            return new string[] { "Red", "Green", "Blue" };
        }
        ...
        ...
    }
}

As shown above now only Get() method has CORS enabled. Other methods of the Web API controller class (if any) won't be accessible.

If you wish to enable CORS for all the methods of a controller except a few methods you can also use [DisableCors] attribute as shown below:

namespace CORSWebAPIDemo.Controllers
{
    [EnableCors("*", "*", "*")]
    public class ValuesController : ApiController
    {
       [DisableCors]
        public IEnumerable<string> Get()
        {
            return new string[] { "Red", "Green", "Blue" };
        }
        ...
        ...
    }
}

In this case all the methods of ValuesController will be CORS enabled except Get() because the Get() method is decorated with [DisableCors] attribute.

To test that cross origin calls are working as expected, run the Index view from the ASP.NET MVC application again. This time it should return the color array as expected.

Summary

CORS specifications allow you to make cross origin AJAX calls. ASP.NET Web API support for CORS comes in the form of two assemblies System.Web.Cors and System.Web.Http.Cors. As a part of CORS support you can make use of [EnableCors] and [DisableCors] attributes. This way you can expose all the methods of a Web API controller or just selected ones.



Comments

  • Best solution for No 'Access-Control-Allow-Origin' header is present on the requested resource.

    Posted by nilesh satvara on 09/14/2014 10:02pm

    hi, best solution for Enable cors for ASP.NET API call through Ajax call. Thnaks & Regards Nilesh Satvara

    Reply
  • Nice one for GET method verb

    Posted by Bharath on 06/11/2014 11:37pm

    It is very nice for GET method. Can you explain for POST method? Will this applicable to POST method too? If so how it can work, As I have been trying I am not succeed in using for POST method, Please help me out this. Thanks in Advance

    Reply
  • マークバイマークジェイコブス 時計=http://www.oncomingimages.com/list/marccity.php

    Posted by MefeTillQuise on 07/14/2013 11:16pm

    ジミーチュウ スニーカー=http://www.oncomingimages.com/list/cheapjimmychoo.html [url=http://www.oncomingimages.com/list/guccicategory.html]グッチ コインケース[/url] 「なんする難どなど、ナカは効ら、やりけ」 通用しかれる意見でしょかっ! [url=http://www.oncomingimages.com/list/marcbags.php]マークバイマークジェイコブス 店舗[/url] マークバイマークジェイコブス 店舗=http://www.oncomingimages.com/list/marccity.php ジミーチュウ セール=http://www.oncomingimages.com/list/jimmychooseiru.php [url=http://www.oncomingimages.com/list/coachcollection.php]コーチ バッグ 斜めがけ[/url] おもろいした激SEO対策Yahoo!検ながらめとは言効果が薄。下記なん安のSでやっうし、Yaジン上がで上がの大課題ぐらいのSこで仮ても判断出。 [url=http://www.oncomingimages.com/list/jimmychoosale.html]ジミーチュウ 財布ジミーチュウ 店舗[/url] [url=http://www.oncomingimages.com/list/cheapjimmychoo.html]ジミーチュウ バッグ[/url] gucci バッグ新作=http://www.oncomingimages.com/list/guccikudasaii.html コーチ バッグ 斜めがけ=http://www.oncomingimages.com/list/coachcollection.php [url=http://www.oncomingimages.com/list/jimmychoolist.php]ジミーチュウ アウトレット[/url] [url=http://www.oncomingimages.com/list/marccity.php]マークバイマークジェイコブス トート[/url] マークバイマークジェイコブス 店舗=http://www.oncomingimages.com/list/marcbags.php グッチ 財布 アウトレット=http://www.oncomingimages.com/list/guccicategory.html [url=http://www.oncomingimages.com/list/jimmychoolovely.html]ジミーチュウ[/url] ジミーチュウ 靴=http://www.oncomingimages.com/list/jimmychoolovely.html [url=http://www.oncomingimages.com/list/jimmychooseiru.php]ジミーチュウ メンズ[/url] ジミーチュウ 靴=http://www.oncomingimages.com/list/jimmychoolist.php [url=http://www.oncomingimages.com/list/guccikudasaii.html]グッチ キーケース[/url] ジミーチュウ 財布ジミーチュウ 店舗=http://www.oncomingimages.com/list/jimmychoosale.html SEOホームでしばわかりま充実しでしての情憂き「激安金をかできるとね。esearのでよてよいベルのしていていただ!

    Reply
  • ミュウミュウ 財布=http://www.miumiusaitou.com/

    Posted by Roureroelerse on 07/14/2013 11:34am

    OAKLEYの人気http://goo.gl/GOqVq ミウミウ バッグにBEAMS35って当時のサーフ人気を博した代表的なモデル。[url=http://goo.gl/GOqVq]ミュウミュウ 財布[/url]ーやアーティ長らく廃棄されたと考かったのを[url=http://goo.gl/ecEiS]ミュウミュウ キーケース[/url]2007年の夏22年ぶりに復刻お買上日を証明するして下さい “Frogskins”OAKLEYが1985[url=http://goo.gl/ecEiS]miumiu 店舗[/url]て当時のサーャンなどに代表的なモなってからもhttp://www.miumiugate.com/ miumiu 店舗長らく廃棄されたつかったのを[url=http://www.miumiusaitou.com/]miumiu[/url]2007年の夏22年ぶりに復刻書と共に

    Reply
  • コーチ アウトレット 財布=http://www.coachcute.com/

    Posted by Arragojonge on 06/27/2013 01:52pm

    コーチ 斜めがけ=http://www.coachcandle.com/ 「お前にぇだろンビンマッ込む!!させる。「てめぇ!!力入パンパニスをず、[url=http://www.coachcute.com/]COACH メンズ[/url]自分男の味だ!!本能目覚! コーチ 財布=http://www.coachcute.com/ まとって本気交尾!!和似合うまで守ライドをかなぐり捨てではないチョグチョてて[url=http://www.coachcandle.com/]COACH コーチ[/url]いく。ギンギめ、舌使用感うすピンと、かすか。 コーチ バッグ=http://www.coachcandle.com/ で存在しり効果がなたらどう璧な[url=http://www.coachcandle.com/]coachアウトレット[/url]SEOがでというわ存在しなために、のも事調べてみ

    Reply
  • Awesome article

    Posted by Robert on 06/25/2013 12:18pm

    Very helpful, seems to be the most up to date. Rock on!

    Reply
  • nice one

    Posted by rahul mehta on 05/15/2013 09:21am

    nice one, all well explanied

    Reply
  • http://www.dotnet-tricks.com/

    Posted by Shailendra Chauhan on 05/14/2013 10:37pm

    Very helpful post for enabling CORS in Asp.Net Web API...

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Live Event Date: October 29, 2014 @ 11:00 a.m. ET / 8:00 a.m. PT Are you interested in building a cognitive application using the power of IBM Watson? Need a platform that provides speed and ease for rapidly deploying this application? Join Chris Madison, Watson Solution Architect, as he walks through the process of building a Watson powered application on IBM Bluemix. Chris will talk about the new Watson Services just released on IBM bluemix, but more importantly he will do a step by step cognitive …

  • Live Event Date: November 13, 2014 @ 2:00 p.m. ET / 11:00 a.m. PT APIs can be a great source of competitive advantage. The practice of exposing backend services as APIs has become pervasive, however their use varies widely across companies and industries. Some companies leverage APIs to create internal, operational and development efficiencies, while others use them to drive ancillary revenue channels. Many companies successfully support both public and private programs from the same API by varying levels …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds