Introduction
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
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
{
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 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)
{
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.
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);
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 }
);
}
}
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.
- Origins is "
http://localhost:18479
" - Header is "
*
", it allows everything of header related issue - 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! :)