Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Using CORS in ASP.NET WebAPI Without Being a Rocket Scientist

0.00/5 (No votes)
9 Jul 2013 1  
This article will discuss the steps necessary to implement and enhance CORS support within ASP.NET WebAPI allowing you to handle CORS Requests at a Global, Controller, or Action level to provide more flexibility when working with possible cross-origin requests.

If you have done any extensive work with AJAX calls, then the odds are that you have fun into an unfriendly (only for security purposes) mechanism that will have your request ground to a halt and its name is CORS (Cross Origin Resource Sharing). Most commonly, this will occur when you are attempting to pull data from a source other than where the request originated from (which raises flags in the security department) although the requests may often be legitimate.

This article will discuss the steps necessary to implement and enhance CORS support within ASP.NET WebAPI allowing you to handle CORS Requests at a Global, Controller, or Action level to provide more flexibility when working with possible cross-origin requests.

A Course on CORS

Cross Origin Resource Sharing (CORS) as previously mentioned is a security mechanism that allows web pages, sites and applications to make AJAX calls and HttpRequests to other domains.

These cross-domain requests are forbidden within browsers that lack CORS due to famous same-origin policy for web requests (which basically states that scripts should only be permitted to run from the domain they originated from) which could lead to nasty things like XSS attacks that translate into you (and your users) having a bad day.

An example CORS request can easily be created by using something like a very basic AJAX call to attempt to access today’s Google doodle:

<script type='text/javascript'>
     $(function(){
         //Create a simple AJAX Request to Google and alert the results
         $.ajax({ url: "http://www.google.com", success: function(data){
             alert(data); //Spoiler Alert: This will not work.
         }});
     });
 </script>

and if you check out the console area of your browser – you’ll see something that looks a bit like this:

Image Demonstrating CORS in Action

The result of a basic demo within JSBin that attempted to access Google. It didn’t go well.

Too Legit To Quit

CORS requests can actually have legitimate purposes aside from scraping screens and data from other domains too. Consider the following situation where you have two sites being hosted:

As you can see above, groundcontrol.com features a WebAPI that you may want to attempt to consume services from using majortom.com. However, due to the way that CORS works, it will recognize these two sites as coming from different origins as they have different hosts (ports and protocols can also constitute different origins) and it will block these requests even though you own both of these domains for security reasons (it doesn’t really care that you own them).

Fear not. Not all requests of this type are illegitimate and CORS features the necessary tools and protocols for handling legit cross-domain and cross-origin requests.

Ground Control to Major Tom

To demonstrate this functionality, we can create a very basic harness to make an AJAX Request that would be considered cross-domain between these two applications. Firstly, we will go into the Web API project (Ground Control) and create a very simple action to send out to our soon to be lonely astronaut.

Within the ValuesController of the WebAPI Project, create the following action:

public class ValuesController : ApiController
{
        public string Get()
        {
             return "Can you hear me Major Tom?";
        }
 }

In order to test that this is working properly, we will also create a view that will perform an AJAX call to this project and retrieve our message:

<head runat="server">
   <meta name="viewport" content="width=device-width" />
   <title>Ground Control</title>
   <!-- jQuery Reference to handle AJAX call -->
   <script src="@Url.Content("~/Scripts/jquery-1.8.2.js")"></script>
   <!-- Our script to actually fire the call itself -->
   <script type="text/javascript">
       //When the page loads
       $(function () {
          //Fire this AJAX call
          $.ajax({
             url: "http://localhost:1337/api/values",
             type: "GET",
             success: function (data) {
                //Grab our data from Ground Control
                alert(data);
             },
             error: function (event) {
                //If any errors occurred - detail them here
                alert("Transmission Failed. (An error has occurred)");
             }
         });
      });
  </script>
</head>

Notice that we have explicitly defined this as running on port 1337, which can easily be set through the Properties of your Application (for demonstration purposes):

 

For this example, we will want to ensure that our Web API service is running at a specific port (so it can be more easily targeted)

For this example, we will want to ensure that our Web API service is running at a specific port (so it can be more easily targeted) and then when we navigate to the Home Controller’s Index View, we will be presented with our AJAX Request from the WebAPI call:

 

Stepping through the Door

Now it doesn’t do much good to have our Ground Control communicating with themselves, so let's try sending these transmissions to our acclaimed astronaut Major Tom who is deep in the depths of space where there is no doubt all types of CORS-related interference to mess with our transmission.

To do this, we will create a very basic MVC Controller within the same solution to function as our Major Tom (it will be a very basic Empty MVC4 Project). Within this project, we will take the following steps:

  • Create a HomeController (eerily similar to the one within the WebAPI Project)
  • Create a View for the Index Action of the Home Control (again so very similar to the WebAPI project)
  • Copy the exact contents of the Index View from the WebAPI Project into the corresponding MVC View

After performing these steps, we are going to attempt to run our MVC Project to see if we can make contact with Ground Control:

The Request from Ground Control to Major Tom failed (further inspection will reveal CORS prevented it)

The Request from Ground Control to Major Tom failed (further inspection will reveal CORS prevented it)

Although this application was targeting the proper URL and port of our WebAPI project, the transmission did not go through successfully. Using the Developer Tools (F12) within your favorite browser, you can check out the Console to see exactly what the cause of the error was:

As you can see by the Access-Control-Allow-Origin error, CORS blocked the access attempt.

As you can see by the Access-Control-Allow-Origin error, CORS blocked the access attempt.

As you might have expected, CORS determined that the request that was being made within the AJAX call was a cross-browser / cross-domain request and it quickly denied it. So it appears that Ground Control will actually need to determine a method to get this message out to Major Tom (our MVC Project) in time.

Technical Difficulties with Ground Control

This issue can be resolved by making the following change within the web.config file of our WebAPI:

<system.webServer>
    <httpProtocol>
        <customHeaders>
            <!-- Adding the following custom HttpHeader 
                 will help prevent CORS from stopping the Request-->
            <add name="Access-Control-Allow-Origin" value="*" />
        </customHeaders>
    </httpProtocol>
</system.webServer>

Adding the Access-Control-Allow-Origin header with a value set to an asterisk (wildcard) will allow any origin to make requests to the Web API. So after making these changes within our WebAPI Project, we can again try running the MVC Application to see if it can now properly receive the transmission being sent from Ground Control:

Major Tom (MVC) successfully receives a CORS Response from Ground Control (WebAPI)

Major Tom (MVC) successfully receives a CORS Response from Ground Control (WebAPI)

So with the minor addition of the Access-Control-Allow-Origin header, we can successfully make CORS requests in between different applications using Web API. If you want to test this out or expand upon the functionality in this example, you can download it below:

Stay tuned for more from Major Tom.

This post reviewed over a very basic method of enabling CORS Requests to be made using ASP.NET Web API, however simply modifying an HTTP Header manually is not the only method for handling this. In a following post, I’ll elaborate a bit more on some of the other methods that can be used to handle CORS Requests as well as some of Microsoft’s planned changes to allow for CORS functionality to be integrated into Web API Projects.

Filed under: CodeProject, Development

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here