Cross Domain Using CORS And JSONP

What is SOP?

Same Origin Policy, also called Single Origin Policy, is a security measure which restricts a web page to make AJAX requests only within the same domain. Browser security prevents a web page from making AJAX requests to another domain.

If we try to hit the different domains in AJAX class, then we will get the below error,

Cross Domain using CORS and JSONP

Let’s see this with an example. Create two projects (Server and Client) in Visual Studio.

Server

The project named “Server”: We will use Web API as a Server/Service in this project.

  1. Create a new project in visual studio → select Asp.Net Web Application

    Cross Domain using CORS and JSONP

  2. Under the Templates Window→ select Web API and click OK,

    Cross Domain using CORS and JSONP

  3. Add a controller (e.g. StudentController) in the Web API by right-clicking on the Controller folder. Select add -> controller from the menu list. Name the controller “StudentController” and select the Empty template.

  4. Add the below code in the StudentController,
    1. public class StudentController: ApiController {  
    2.     public IEnumerable < Student > Get() {  
    3.         return Student.GetAllStudents();  
    4.     }  
    5. }  
  5. Right click on the Models folder and select add -> class from the menu list. Name the class file as Student.cs. Copy the below code to the class file named “Student.cs”.
    1. namespace Service.Models {  
    2.     public class Student {  
    3.         public int Id {  
    4.             get;  
    5.             set;  
    6.         }  
    7.         public string FirstName {  
    8.             get;  
    9.             set;  
    10.         }  
    11.         public string LastName {  
    12.             get;  
    13.             set;  
    14.         }  
    15.         public string Gender {  
    16.             get;  
    17.             set;  
    18.         }  
    19.         public static IEnumerable < Student > GetAllStudents() {  
    20.             return new List < Student > () {  
    21.                 new Student() {  
    22.                         Id = 1, FirstName = "Raj", LastName = "Kumar", Gender = "Male"  
    23.                     },  
    24.                     new Student() {  
    25.                         Id = 2, FirstName = "Karan", LastName = "Sharma", Gender = "Male"  
    26.                     },  
    27.                     new Student() {  
    28.                         Id = 3, FirstName = "Neha", LastName = "Sharma", Gender = "Female"  
    29.                     },  
    30.                     new Student() {  
    31.                         Id = 4, FirstName = "Maninder", LastName = "Singh", Gender = "Male"  
    32.                     }  
    33.             };  
    34.         }  
    35.     }  
    36. }  

NOTE
I have created a Student.cs class to get the dummy data from the Student class. Instead of creating a Student class you can use Entity Framework with SQL Server to fetch the data.

Once you are done with the above code, your Web API service is ready to use. Let's make a call to the Web API to check if everything is working as expected. Browse the service in the web browser and append the following lines in the URL to hit our StudentController.

<http://domain:port/api/student>

The above URL can vary according to the port number. In my case, my port number is 60545.

<http://localhost:60545/api/student>

After filling the above URL in the browser, press enter or go button in the browser. You will get the below XML in the browser.

Cross Domain using CORS and JSONP

So, our Web API Service is up and running as expected. Now, it's time to create a client project which can call/consume this web service.

Project Client

We are using Web Form, you can create one simple HTML page as well. The below example explains Web Form Project as a client.

  1. Right Click on the Solution Tab → Add→ New Project→ ASP.NET Web Application

    Cross Domain using CORS and JSONP

  2. Under the Template pane, select Web Forms and click Ok.

    Cross Domain using CORS and JSONP

  3. Right click on the Project and Add New HTML page. Name that page as Students.html.

    Cross Domain using CORS and JSONP

  4. Open the Students.html page. Delete the existing code and paste the below code in the HTML file. In the client code, we have imported jQuery file. Under the AJAX call, we are calling our Web API service.
    1. <!DOCTYPE html>  
    2. <html xmlns="http://www.w3.org/1999/xhtml">  
    3.   
    4. <head>  
    5.     <title></title>  
    6.     <script src="Scripts/jquery-1.10.2.min.js"></script>  
    7.     <script> $(document).ready(function () {  
    8.   
    9. $('#btnAll').click(function () {  
    10. $.ajax({  
    11.    type: 'Get',  
    12.    url: 'http://localhost:60545/api/student',  
    13.    dataType: 'json',  
    14. success: function myfunction(data) {  
    15.    $.each(data, function myfunction(index, val) {  
    16.       $('#ulStudents').append('<li>' + val.FirstName + '' + val.LastName + '</li>');  
    17.    });  
    18. }  
    19.   
    20. });  
    21. });  
    22.   
    23. });  
    24. </script>  
    25. </head>  
    26.   
    27. <body>  
    28.     <input type="button" id="btnAll" value="Get All Students" />  
    29.     <ul id="ulStudents"></ul>  
    30. </body>  
    31.   
    32. </html>  

That's it -- we are done with both the Client and Service code. It's time to test our functionality.

Run Client and Server Project

Click on the “Get All Students” button, you will see nothing happens. Open the developer tool of the browser, you will see an error given below,

Cross Domain using CORS and JSONP

The above error describes that for the security reason browsers does not allow cross-domain AJAX requests. How to fix this issue? There are two ways to get around this problem.

Two Approaches for cross-domain AJAX requests,

  1. Using JSONP (JSON with Padding)
  2. Enabling CORS (Cross-Origin Resource Sharing)

What is JSONP?

JSONP stands for JSON with Padding. It's a process used for sending the data cross domain without the use of XMLHttpRequest object. JSONP wraps the data/result in a function.

Implementing JSONP in Server Side (Web API Service)

  1. Select the Web API project and open the NuGet Package Console. In the console window type the below command,

    Install-package WebApicontrib.formatting.jsonp

    The above command will install dependant jsonp files according to the framework.
  1. Open the WebApiConfig.cs file and update the code with below code.
    1. var jsonpFormatter = new JsonpMediaTypeFormatter(config.Formatters.JsonFormatter);  
    2. config.Formatters.Insert(0, jsonpFormatter);  
  1. Open the Student.html file from the Client Project. Change the dataType of the AJAX class,

    dataType: 'jsonp'
  1. Build the project and re-run the scenario.

    Cross Domain using CORS and JSONP

What is CORS in Web API?

CORS is a W3C standard that allows you to bypass the same origin policy adopted by the browsers which restrict access from one domain of resources belonging to another domain. CORS works on the principle of same origin policy.

Let's remove our previous JSONP references from our existing project so we can achieve the functionality using CORS.

On the Client side, change the datatype property of AJAX back to “json”

dataType: 'json',

On the Server Side, comment the following lines,

  1. config.MapHttpAttributeRoutes();  
  2. config.Routes.MapHttpRoute(name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new {  
  3.     id = RouteParameter.Optional  
  4. });  
  5. //var jsonpFormatter = new JsonpMediaTypeFormatter(config.Formatters.JsonFormatter);  
  6. //config.Formatters.Insert(0, jsonpFormatter);  

Install the following package on the Web API Server Project using Package Manager Console window.

Install-Package Microsoft.AspNet.WebApi.Cors

Cross Domain using CORS and JSONP

Add the following code in the WebApiConfig.cs.

EnableCorsAttribute takes three parameters.

First parameter

Provide the list of URLs of clients who want to access this Web API.

i.e. “http://abc.com, http://bcd.com”

Second Parameter

The headers parameter of the [EnableCors] attribute specifies which author request headers are allowed.

i.e. headers: "accept,content-type,origin,x-my-header"

Third Parameter

It accepts the method that you want to expose with the client (Get, Post, Put, Delete)

  1. EnableCorsAttribute _cors = new EnableCorsAttribute("*""*""*");  
  2. config.EnableCors(_cors);  

NOTE
The above setting will get applied on Global Level. It can be applied on Controller level as well.

Controller Level 

  1. [EnableCorsAttribute("*""*""*")]  
  2. public class StudentController: ApiController {  
  3.     public IEnumerable < Student > Get() {  
  4.         return Student.GetAllStudents();  
  5.     }  
  6. }  
Build the Solution and re-run the scenario.

Cross Domain using CORS and JSONP

Thanks.