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.
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
- 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, both database and table have been created. The image, given below, is of the 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'[email protected]', N'017511111111', NULL)
- GO
- INSERT [dbo].[StudentMgt] ([StudentID], [FirstName], [LastName], [Email], [MobileNo], [Address]) VALUES (2, N'Mona ', N'Akter', N'[email protected]', N'017511111112', NULL)
- GO
- INSERT [dbo].[StudentMgt] ([StudentID], [FirstName], [LastName], [Email], [MobileNo], [Address]) VALUES (3, N'Rashedul ', N'Haque
- ', N'[email protected]', 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, 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.
Once you click OK, a project MVC pattern's structure with the 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. The picture is given below:
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:
- public class StudentController: ApiController
- {
-
- private StudentMgtEntities _dbContext = null;
-
- public StudentController()
- {
-
- _dbContext = new StudentMgtEntities();
- }
- [HttpGet]
-
- 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 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:
- public static class WebApiConfig
- {
- public static void Register(HttpConfiguration config)
- {
-
- config.Formatters.Clear();
- config.Formatters.Add(new JsonMediaTypeFormatter());
-
- config.SuppressDefaultHostAuthentication();
- config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
-
- 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, which are:
- 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. We can see the picture, given below, as to how we run our mobile app.
We can see the screen, given below, in our Browser.
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:
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.
- <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, which allow the methods like GET,POST,PUT,DELETE,OPTIONS with the 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);
-
- config.Formatters.Clear();
- config.Formatters.Add(new JsonMediaTypeFormatter());
-
- config.SuppressDefaultHostAuthentication();
- config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
-
- config.MapHttpAttributeRoutes();
- config.Routes.MapHttpRoute(name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new {
- id = RouteParameter.Optional
- });
- }
- }
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.
- 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 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.
- protected void Application_BeginRequest()
- {
- if (Request.Headers.AllKeys.Contains("Origin") && Request.HttpMethod == "OPTIONS")
- {
- Response.Flush();
- }
- }
We are finished with our code. Now, we will check:
Wow, the work is done.
Hope, this will be helpful. Happy coding.