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

Datetime:2016-08-23 04:42:45          Topic: ASP.NET           Share

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 calling our web API in mobile application. Here I am going to use two applications, one is ASP.NET web application and another one is Mobile Application which made Ionic platform.

Background

Cross (Cross-origin resource Sharing)is a World Wide Web Consortium. Basically, it is considered part’s HTML5. Mobile app will call XML Http Request for Http verb ( GET , POST , PUT , Delete , etc.) to the ASP.NET Web application by using API. By Default, Cross origin Request is disabled in ASP.NET Web API. But when we need call ASP.NET Web API, then it needs to be enabled. We will focus more on our ASP.NET Web API than Mobile Application in this article.

Figure: 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:

CREATE DATABASE StudentMgt;

To create Table:

USE [StudentMgt]
GO

/****** Object:  Table [dbo].[Student]    Script Date: 8/17/2016 9:10:38 PM ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[Student](
	[StudentID] [int] IDENTITY(1,1) NOT NULL,
	[FirstName] [nvarchar](50) NULL,
	[LastName] [nvarchar](50) NULL,
	[Email] [nvarchar](50) NULL,
	[MobileNo] [nvarchar](30) NULL,
	[Address] [nvarchar](250) NULL,
 CONSTRAINT [PK_tbl_Student] PRIMARY KEY CLUSTERED 
(
	[StudentID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, 
 ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

Finally database and table both have been created. Below is the following picture of table:

We will use some demo data for our work prospective.

GO
INSERT [dbo].[StudentMgt] ([StudentID], [FirstName], [LastName], [Email], [MobileNo], [Address]) _
VALUES (1, N'Pritu ', N'PS', N'Pritu@gmail.com', N'017511111111', NULL)
GO
INSERT [dbo].[StudentMgt] ([StudentID], [FirstName], [LastName], [Email], [MobileNo], [Address]) _
VALUES (2, N'Mona ', N'Akter', N'Mona@yahoo.com', N'017511111112', NULL)
GO
INSERT [dbo].[StudentMgt] ([StudentID], [FirstName], [LastName], [Email], [MobileNo], [Address]) _
VALUES (3, N'Rashedul ', N'Haque
', N'Rashedul@gmail.com', N'017511111113', NULL)
GO
INSERT [dbo].[StudentMgt] ([StudentID], [FirstName], [LastName], [Email], [MobileNo], [Address]) _
VALUES (4, N'Mamun ', N'Rashed', N'Mamun @gmail.com', N'017511111114', NULL)
GO

Creating ASP.NET Web Application

Click File, New, and Project and select ASP.NET Web Application and give project name, location and click ok button once. 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.

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

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. Below is the following picture:

Create StudentController

Right click on your Controller folder and select Add, click Controller, select Web API 2 Controller-Empty Once click add, and give controller name. I have given my controller name " StudentController ". Wow, our StudentController has been created. Below is the code:

public class StudentController : ApiController
   {
       // StudentMgtEntites object point
       private StudentMgtEntities _dbContext = null;
       // Constructor
       public StudentController()
       {
           // create instance of an object
           _dbContext = new StudentMgtEntities();
       }
       [HttpGet]
       // Get Students List
       public List<Student> GetStudents()
       {
           List<Student> students = _dbContext.Students.ToList();
           return students;
       }
   }

Our Student Controller has been created. Now we will check:

Wow, our API worked. We got XML format data. But we will work with json format. We have to change in WebApiConfig class for json format data. Below is the code:

public static class WebApiConfig
   {
       public static void Register(HttpConfiguration config)
       {
           // Web API configuration and services
           config.Formatters.Clear();
           config.Formatters.Add(new JsonMediaTypeFormatter());
           // Configure Web API to use only bearer token authentication.
           config.SuppressDefaultHostAuthentication();
           config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));

           // Web API routes
           config.MapHttpAttributeRoutes();

           config.Routes.MapHttpRoute(
               name: "DefaultApi",
               routeTemplate: "api/{controller}/{id}",
               defaults: new { id = RouteParameter.Optional }
           );
       }
   }

Actually, I have added two lines for json data.

config.Formatters.Clear();
config.Formatters.Add(new JsonMediaTypeFormatter());

Again, we will check our 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.

Now we will run our mobile app. How we run our mobile app we can see in the below picture.

We can see the below screen in our browser.

It ran successfully, but I do not see any data. Let's go find out why data could not load. I got an error. The error is:

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

Then please keep the below code in webconfig and within <system.webServer> part:

<httpProtocol>
    <customHeaders>
      <add name="Access-Control-Allow-Origin" value="*" />
      <add name="Access-Control-Allow-Headers" value="Content-Type" />
      <add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" />
    </customHeaders>
  </httpProtocol>

We have just setup Access control to allow methods like GET , POST , PUT , DELETE , OPTIONS with header and origin. Install " Microsoft.AspNet.WebApi.Cors " package using NuGetManager.

We will modify WebApiConfig class.

public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {          
            var cors = new EnableCorsAttribute("http://localhost:18479", "*", "*");
            config.EnableCors(cors);
            // Web API configuration and services
            config.Formatters.Clear();
            config.Formatters.Add(new JsonMediaTypeFormatter());
            // Configure Web API to use only bearer token authentication.
            config.SuppressDefaultHostAuthentication();
            config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
            // Web API routes
            config.MapHttpAttributeRoutes();
            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );
        }
    }

Below lines are Register method. but this method takes a parameter of HttpConfiguration class. This class represents a Configuration of httpServer instances. We have declared EnableCorsAttribute class for initializing a new instance of the EnableCorsAttribute class. But this class takes three parameter for constructor like origins, headers and method here.

  1. Origins is " http://localhost:18479 "
  2. Header is " * ", it allows everything of header related issue
  3. Method is " * ", it allows everything of method related issue
var cors = new EnableCorsAttribute("http://localhost:18479", "*", "*");
 config.EnableCors(cors);

We have modified our Global.asax class:

public class WebApiApplication : System.Web.HttpApplication
    {
        protected void Application_BeginRequest()
        {
            if (Request.Headers.AllKeys.Contains("Origin") && Request.HttpMethod == "OPTIONS")
            {
                Response.Flush();
            }
        }
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            GlobalConfiguration.Configure(WebApiConfig.Register);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
        }
    }

we have added 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 ", then ends all currently buffered output to the client.

protected void Application_BeginRequest()
        {
            if (Request.Headers.AllKeys.Contains("Origin") && Request.HttpMethod == "OPTIONS")
            {
                Response.Flush();
            }
        }

Our code has finished. Now we will check:

It's work done. Hope this will be helpful. Happy coding!





About List