How To Enable Cross Origin Request In ASP.NET Web API

In this article, we are going to learn, how we can enable cross origin request in ASP.NET Web API. We know that ASP.NET Web API is platform independent. Recently, I came across a need for calling our Web API in mobile Applications. Here, I am going to use two Applications, where one is ASP.NET Web Application and another one is Mobile Application, which is made on Ionic platform.

Background

Cross (Cross-origin resource Sharing) is a World Wide Web Consortium. Basically, it is considered part of HTML5. Mobile app will call XML Http Request for Http verb (GET, POST, PUT, Delete, etc.) to the ASP.NET Web Application, using API. By default, Cross origin Request is disabled in ASP.NET Web API. When we need to call ASP.NET Web API, it needs to be enabled. We will focus more on our ASP.NET Web API, Mobile Application in this article.
Mobile App and Web API
Fig: Request overview between Mobile App and Web API.

Firstly, we will create a database

The following query can be used to create a database in your SQL Server.

To create Database

  1. CREATE DATABASE StudentMgt;  
  2. To create Table  
  3. USE [StudentMgt]  
  4. GO  
  5.   
  6. /****** Object: Table [dbo].[Student] Script Date: 8/17/2016 9:10:38 PM ******/  
  7. SET ANSI_NULLS ON  
  8. GO  
  9.   
  10. SET QUOTED_IDENTIFIER ON  
  11. GO  
  12.   
  13. CREATE TABLE [dbo].[Student](  
  14. [StudentID] [int] IDENTITY(1,1) NOT NULL,  
  15. [FirstName] [nvarchar](50) NULL,  
  16. [LastName] [nvarchar](50) NULL,  
  17. [Email] [nvarchar](50) NULL,  
  18. [MobileNo] [nvarchar](30) NULL,  
  19. [Address] [nvarchar](250) NULL,  
  20. CONSTRAINT [PK_tbl_Student] PRIMARY KEY CLUSTERED   
  21. (  
  22. [StudentID] ASC  
  23. )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ONON [PRIMARY]  
  24. ON [PRIMARY]  
  25.   
  26. GO  
Finally, both database and table have been created. The image, given below, is of the table:

table

We will use some demo data for our work prospective.
  1. GO  
  2. INSERT [dbo].[StudentMgt] ([StudentID], [FirstName], [LastName], [Email], [MobileNo], [Address]) VALUES (1, N'Pritu ', N'PS', N'Pritu@gmail.com', N'017511111111'NULL)  
  3. GO  
  4. INSERT [dbo].[StudentMgt] ([StudentID], [FirstName], [LastName], [Email], [MobileNo], [Address]) VALUES (2, N'Mona ', N'Akter', N'Mona@yahoo.com', N'017511111112'NULL)  
  5. GO  
  6. INSERT [dbo].[StudentMgt] ([StudentID], [FirstName], [LastName], [Email], [MobileNo], [Address]) VALUES (3, N'Rashedul ', N'Haque  
  7. ', N'Rashedul@gmail.com', N'017511111113', NULL)  
  8. GO  
  9. INSERT [dbo].[StudentMgt] ([StudentID], [FirstName], [LastName], [Email], [MobileNo], [Address]) VALUES (4, N'Mamun ', N'Rashed', N'Mamun @gmail.com', N'017511111114'NULL)  
  10. GO 
Creating ASP.NET Web Application

Click File, New, Project, select ASP.NET Web Application and will give the project name, location and click OK button. From the following pop up,  we will select the Web API with Add folders and core reference for MVC Web API will be auto selected.

MVC Web API

Once you click OK, a project MVC pattern's structure with the core references will be created.

structure

Create Entity Data Model

Right click on your Model folder and click new, select ADO.NET Entity Data Model. Follow the steps given. Once you have done the process, you can see the EDMX file and other files in your Model folder. Here, I gave StudentMgtEntities for our Entity data model name. Now, you can see a file with EDMX extension has been created. The picture is given below:

Model

Create StudentController

Right click on your Controller folder, select Add, click Controller, select Web API 2 Controller-Empty. Click add and give the controller name. I have given my controller name "StudentController". Wow, our StudentController has been created. The code is given below:
  1. public class StudentController: ApiController   
  2. {  
  3.     // StudentMgtEntites object point  
  4.     private StudentMgtEntities _dbContext = null;  
  5.     // Constructor   
  6.     public StudentController()   
  7.         {  
  8.             // create instance of an object  
  9.             _dbContext = new StudentMgtEntities();  
  10.         }  
  11.         [HttpGet]  
  12.         // Get Students List  
  13.     public List < Student > GetStudents()   
  14.     {  
  15.         List < Student > students = _dbContext.Students.ToList();  
  16.         return students;  
  17.     }  
  18. }  
Our Student Controller has been created. Now, we will check.

code

Wow, our API works. We got XML format data but we will work with JSON format. We have to change in WebApiConfig class for JSON format data. The code is given below:
  1. public static class WebApiConfig   
  2. {  
  3.     public static void Register(HttpConfiguration config)   
  4.     {  
  5.         // Web API configuration and services  
  6.         config.Formatters.Clear();  
  7.         config.Formatters.Add(new JsonMediaTypeFormatter());  
  8.         // Configure Web API to use only bearer token authentication.  
  9.         config.SuppressDefaultHostAuthentication();  
  10.         config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));  
  11.         // Web API routes  
  12.         config.MapHttpAttributeRoutes();  
  13.         config.Routes.MapHttpRoute(name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new {  
  14.             id = RouteParameter.Optional  
  15.         });  
  16.     }  
  17. }  
Actually, I have added two lines for JSON data, which are:
  1. config.Formatters.Clear();  
  2. config.Formatters.Add(new JsonMediaTypeFormatter());  
Again, we will check our API.

API

OK, API has given JSON data. It works correctly.

Now, we will call this API in our mobile Application, which is made by ionic platform.

API

Now, we will run our mobile app. We can see the picture, given below, as to how we run our mobile app.

code

We can see the screen, given below, in our Browser.

screen

Wow, it is run successfully, but I do not see any data. Let's go to find out, why the data could not load. I got an error and the error is:

error

Actually, it was the main focus of our post. Let's solve this error. We will keep the code, given below, in webconfig within <system.webServer> part.

Please keep the code, given below, in webconfig and within <system.webServer> part.
  1. <httpProtocol>  
  2.     <customHeaders>  
  3.         <add name="Access-Control-Allow-Origin" value="*" />  
  4.         <add name="Access-Control-Allow-Headers" value="Content-Type" />  
  5.         <add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" /> </customHeaders>  
  6. </httpProtocol>  
We have just setup Access control, which allow the methods like GET,POST,PUT,DELETE,OPTIONS with the header and origin.

Install "Microsoft.AspNet.WebApi.Cors" package, using NuGetManager.

NuGetManager

We will modify WebApiConfig class.
  1. public static class WebApiConfig  
  2. {  
  3.     public static void Register(HttpConfiguration config)  
  4.   {  
  5.         var cors = new EnableCorsAttribute("http://localhost:18479""*""*");  
  6.         config.EnableCors(cors);  
  7.         // Web API configuration and services  
  8.         config.Formatters.Clear();  
  9.         config.Formatters.Add(new JsonMediaTypeFormatter());  
  10.         // Configure Web API to use only bearer token authentication.  
  11.         config.SuppressDefaultHostAuthentication();  
  12.         config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));  
  13.         // Web API routes  
  14.         config.MapHttpAttributeRoutes();  
  15.         config.Routes.MapHttpRoute(name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new {  
  16.             id = RouteParameter.Optional  
  17.         });  
  18.     }  
  19. }  
Register method is used below but this method takes a parameter of HttpConfiguration class. This class represents a configuration of httpServer instances. We have declared EnableCorsAttribute class to initialize a new instance of the EnableCorsAttribute class but this class takes three parameters  for the constructor like origins, headers and method.  
  • Origins is "http://localhost:18479".
  • Header is "*", It allows everything of the header related issue.
  • Method is "*",It allows everything of the method related issue.

var cors = new EnableCorsAttribute("http://localhost:18479", "*", "*");
config.EnableCors(cors);

We have modified our Global.asax class.

  1. public class WebApiApplication: System.Web.HttpApplication  
  2. {  
  3.     protected void Application_BeginRequest()   
  4.     {  
  5.         if (Request.Headers.AllKeys.Contains("Origin") && Request.HttpMethod == "OPTIONS")   
  6.         {  
  7.             Response.Flush();  
  8.         }  
  9.     }  
  10.     protected void Application_Start() {  
  11.         AreaRegistration.RegisterAllAreas();  
  12.         GlobalConfiguration.Configure(WebApiConfig.Register);  
  13.         FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);  
  14.         RouteConfig.RegisterRoutes(RouteTable.Routes);  
  15.         BundleConfig.RegisterBundles(BundleTable.Bundles);  
  16.     }  
  17. }  
We have added an Application_BeginRequest method in Global.asax class. Generally,  this method checks Header's all keys. If it contains with "Origin" and Request HttpMethod is "OPTIONS", it ends all currently buffered output to the client.
  1. protected void Application_BeginRequest()   
  2. {  
  3.     if (Request.Headers.AllKeys.Contains("Origin") && Request.HttpMethod == "OPTIONS")   
  4.     {  
  5.         Response.Flush();  
  6.     }  
  7. }  
We are finished with our code. Now, we will check:

output

Wow, the work is done.

Hope, this will be helpful. Happy coding.