Sunteți pe pagina 1din 164

Rest:

List

Q1. What is REST?


Ans. REST stands for Representational State Transfer. This is a protocol for exchanging data
over a distributed environment. REST is an architectural style which treat each service as a
resource and access data by HTTP protocol methods like GET, POST, PUT, and DELETE.
REST-style architectures consist of clients and servers. Clients initiate requests to servers who
process these requests and return responses based on these requests. These requests and
responses are built around the transfer of representations of these resources.

Q2. Explain REST principle?


Ans. REST is a set of principles that define how Web standards, such as HTTP and URIs, are
supposed to be used. There are five important REST principle as given below –
Addressable Resources​ - Each resource should be identified by a URI (unique identifier)
Simple and Uniform Interfaces​ - REST is based on HTTP protocol so use HTTP GET, POST,
PUT and DELETE method to perform actions. This make REST simple and uniform.
Representation Oriented​- Representation of resources are exchanged. GET is used to return
a representation and PUT, POST passes representation to the server so that underlying
resources may change. Representation may be in many formats like XML, JSON etc.
Communicate Stateless​ - An application may has state but there is no client session data
stored on the server. Any session specific data should be held and maintained by the client and
transferred to the server with each request as needed.
Cacheable ​- Clients should be able to cache the responses for further use.

REST and SOAP?


Ans. The difference between REST and SOAP is given below: SOAP REST SOAP stands for
Simple Object Access Protocol REST stands for REpresentational State Transfer. It is an XML
based protocol built on the top of HTTP or sometimes TCP/IP, SMTP. REST is not a protocol
but it is an architectural style i.e. resource-based architecture.
DOT NET TRICKS TRAINING CENTER
B 64, Near SBI Bank, Sector 2 Noida, Metro Noida Sector 15, Uttar Pradesh (India)
www.dotnet-tricks.com, www.dotnettricks.com +91 98 71 749695, +91 120 426 5198
Page79
Training Highlights
Learn from qualified and experienced professional
Small batches to ensure personal attention
Hands-on real application development
Recorded session of your class
Training course material
Prepare yourself for interview and get great jobs
SOAP has specifications for both stateless and stateful implementation. REST is completely
stateless. SOAP enforces message format as XML. REST does not enforces message format
as XML or JSON. SOAP has a defined standard specification. For example, WS-Security is the
specification for implementing security. It has no defined standard specifications. The SOAP
message consists of an envelope which includes SOAP headers and body to store the actual
information you want to send. REST uses the HTTP build-in headers (with a variety of
media-types) to carry meta information and use the GET, POST, PUT and DELETE verbs to
perform CRUD operations. SOAP uses interfaces and named operations to expose your
service. REST uses URI and methods like (GET, PUT, POST, DELETE) to expose resources.
Performance is slow as compared to REST. REST is fast as compared to SOAP.

-------------------------------------------------------------------------------------------------------------------

Fundamental:
Tttt

Q4. What is ASP.NET WEB API?


Ans. ASP.NET WEB API is a framework for building HTTP services that can be consume by a
broad range of clients including browsers, mobiles, iphone and tablets. It is very similar to
ASP.NET MVC since it contains the MVC features such as routing, controllers, action results,
filter, model binders, IOC container or dependency injection. But it is not a part of the MVC
Framework.
It is a part of the core ASP.NET platform and can be used with MVC and other types of Web
applications like ASP.NET WebForms. It can also be used as a stand-alone Web services
application.

ASP.NET WEB API features


1. It supports convention-based CRUD Actions since it works with HTTP verbs GET, POST,
PUT and DELETE.
2. Responses have an Accept header and HTTP status code.
3. Responses are formatted by WEB API’s MediaTypeFormatter into JSON, XML or whatever
format you want to add as a MediaTypeFormatter.
4. It may accepts and generates the content which may not be object oriented like images, PDF
files etc.
5. It has automatic support for OData. Hence by placing the new [Queryable] attribute on a
controller method that returns IQueryable, clients can use the method for OData query
composition.
6. It can be hosted with in the applicaion or on IIS.
7. It also supports the MVC features such as routing, controllers, action results, filter, model
binders, IOC container or dependency injection that makes it more simple and robust.

Q5. Why to choose ASP.NET WEB API?


Ans. Today, a web-based application is not enough to reach it's customers. People are very
smart, they are using iphone, mobile, tablets etc. devices in its daily life. These devices also
have a lot of apps for making the life easy. Actually, we are moving from the web towards apps
world.
DOT NET TRICKS TRAINING CENTER
B 64, Near SBI Bank, Sector 2 Noida, Metro Noida Sector 15, Uttar Pradesh (India)
www.dotnet-tricks.com, www.dotnettricks.com +91 98 71 749695, +91 120 426 5198
Page80
Training Highlights
Learn from qualified and experienced professional
Small batches to ensure personal attention
Hands-on real application development
Recorded session of your class
Training course material
Prepare yourself for interview and get great jobs
So, if you like to expose your service data to the browsers and as well as all these modern
devices apps in fast and simple way, you should have an API which is compatible with browsers
and all these devices.
For example twitter, facebook and Google API for the web application and phone apps.
WEB API is the great framework for exposing your data and service to different-different
devices. Moreover WEB API is open source an ideal platform for building REST-ful services
over the .NET Framework. Unlike WCF Rest service, it use the full featues of HTTP (like URIs,
request/response headers, caching, versioning, various content formats) and you don't need to
define any extra config settings for different devices unlike WCF Rest service.

Why to choose WEB API


1. If we need a Web Service and don’t need SOAP, then ASP.NET WEB API is best choice.
2. It is used to build simple, non-SOAP-based HTTP Services on top of existing WCF message
pipeline.
3. It doesn't have tedious and extensive configuration like WCF REST service.
4. Simple service creation with WEB API. With WCF REST Services, service creation is difficult.
5. It is only based on HTTP and easy to define, expose and consume in a REST-ful way.
6. It is light weight architecture and good for devices which have limited bandwidth like smart
phones.
7. It is open source.

WCF and WEB API and WCF REST and Web Service?
Ans. .NET framework has a number of technologies that allow you to create HTTP services
such as Web Service, WCF and now WEB API. There are following differences among these
four:
Web Service
1. It is based on SOAP and return data in XML form.
2. It supports only HTTP protocol.
3. It is not open source but can be consumed by any client that understands xml.
4. It can be hosted only on IIS.
DOT NET TRICKS TRAINING CENTER
B 64, Near SBI Bank, Sector 2 Noida, Metro Noida Sector 15, Uttar Pradesh (India)
www.dotnet-tricks.com, www.dotnettricks.com +91 98 71 749695, +91 120 426 5198
Page81
Training Highlights
Learn from qualified and experienced professional
Small batches to ensure personal attention
Hands-on real application development
Recorded session of your class
Training course material
Prepare yourself for interview and get great jobs
WCF
1. It is also based on SOAP and return data in XML form.
2. It is the evolution of the web service (ASMX) and support various protocols like TCP, HTTP,
HTTPS, Named Pipes, MSMQ.
3. The main issue with WCF is, its tedious and extensive configuration.
4. It is not open source but can be consumed by any client that understands xml.
5. It can be hosted with in the application or on IIS or using window service.
WCF Rest
1. To use WCF as WCF Rest service you have to enable webHttpBindings.
2. It support HTTP GET and POST verbs by [WebGet] and [WebInvoke] attributes respectively.
3. To enable other HTTP verbs you have to do some configuration in IIS to accept request of
that particular verb on .svc files
4. Passing data through parameters using a WebGet needs configuration. The UriTemplate
must be specified
5. It support XML, JSON and ATOM data format.
WEB API
1. This is the new framework for building HTTP services with easy and simple way.
2. WEB API is open source an ideal platform for building REST-ful services over the .NET
Framework.
3. Unlike WCF Rest service, it use the full features of HTTP (like URIs, request/response
headers, caching, versioning, various content formats)
4. It also supports the MVC features such as routing, controllers, action results, filter, model
binders, IOC container or dependency injection, unit testing that makes it more simple and
robust.
5. It can be hosted with in the application or on IIS.
6. It is light weight architecture and good for devices which have limited bandwidth like smart
phones.
7. Responses are formatted by WEB API’s MediaTypeFormatter into JSON, XML or whatever
format you want to add as a MediaTypeFormatter.
WCF and WEB API?
Ans. The following points help you to choose between WCF and WEB API:
1. Choose WCF when you want to create a service that should support special scenarios such
as one way messaging, message queues, duplex communication etc.
2. Choose WCF when you want to create a service that can use fast transport channels when
available, such as TCP, Named Pipes, or maybe even UDP (in WCF 4.5), and you also want to
support HTTP when all other transport channels are unavailable.
3. Choose WEB API when you want to create resource-oriented services over HTTP that can
use the full features of HTTP (like URIs, request/response headers, caching, versioning, various
content formats).
4. Choose WEB API when you want to expose your service to a broad range of clients including
browsers, mobiles, iphone and tablets.
DOT NET TRICKS TRAINING CENTER
B 64, Near SBI Bank, Sector 2 Noida, Metro Noida Sector 15, Uttar Pradesh (India)
www.dotnet-tricks.com, www.dotnettricks.com +91 98 71 749695, +91 120 426 5198
Page82
Training Highlights
Learn from qualified and experienced professional
Small batches to ensure personal attention
Hands-on real application development
Recorded session of your class
Training course material
Prepare yourself for interview and get great jobs

ASP.NET MVC and ASP.NET WEB API?


Ans. There are following differences between ASP.NET MVC and WEB API:
1. ASP.NET MVC is used to create web applications that return both views and data but
ASP.NET WEB API is used to create full blown HTTP services with easy and simple way that
returns only data not view.
2. WEB API helps to build REST-ful services over the .NET Framework and it also support
content-negotiation(it's about deciding the best response format data that could be acceptable
by the client. it could be JSON,XML,ATOM or other formatted data), self-hosting which are not
in MVC.
3. WEB API also takes care of returning data in particular format like JSON, XML or any other
based upon the Accept header in the request and you don't worry about that. MVC only return
data in JSON format using JsonResult.
4. In WEB API the request are mapped to the actions based on HTTP verbs but in MVC it is
mapped to actions name.
5. ASP.NET WEB API is new framework and part of the core ASP.NET framework. The model
binding, filters, routing and others MVC features exist in WEB API are different from MVC and
exists in the new System.Web.Http assembly. In MVC, these features exist within
System.Web.Mvc. Hence WEB API can also be used with ASP.NET and as a stand-alone
service layer.
6. You can mix WEB API and MVC controller in a single project to handle advanced AJAX
requests which may return data in JSON, XML or any others format and building a full blown
HTTP service. Typically, this will be called WEB API self-hosting.
7. When you have mixed MVC and WEB API controller and you want to implement the
authorization then you have to create two filters one for MVC and another for WEB API since
both are different.
8. Moreover, WEB API is light weight architecture and except the web application it can also be
used with smart phone apps.

Q9. Can you return view by using WEB API method?


Ans. Unlike ASP.NET MVC, WEB API is used to return only data. The data can be string,
JSON, XML, Text etc. It cannot return View like ASP.NET MVC.
DOT NET TRICKS TRAINING CENTER
B 64, Near SBI Bank, Sector 2 Noida, Metro Noida Sector 15, Uttar Pradesh (India)
www.dotnet-tricks.com, www.dotnettricks.com +91 98 71 749695, +91 120 426 5198
Page83
Training Highlights
Learn from qualified and experienced professional
Small batches to ensure personal attention
Hands-on real application development
Recorded session of your class
Training course material
Prepare yourself for interview and get great jobs

Q10. Can you change WEB API action name like ASP.NET MVC?
Ans. Like ASP.NET MVC, you can also change WEB API action name by using ActionName
attribute as given below: [HttpGet] [ActionName("GetProducts")] public IEnumerable<Product>
ProductList() { return db.Products.AsEnumerable(); }

Restrict a WEB API action method


Q11. Can you restrict a WEB API action method to be invoked only by HTTP GET, POST, PUT
or DELETE?
Ans. Like ASP.NET MVC, you can also restrict WEB API action method to be invoked only by a
specific HTTP request by applying HttpGet or HttpPost or HttpPut or HttpDelete attribute.
If you want to restrict an action method for HTTP Get request only then decorate it with HttpGet
action method selector attribute as given below: [HttpGet] public IEnumerable<Product>
ProductList() { return db.Products.AsEnumerable(); }

Q12. How to call WEB API in ASP.NET MVC?


Ans. ASP.NET WEB API can be called by using HttpClient and WEB API address as given
below: public class ProductController : Controller { HttpClient Client = new HttpClient(); Uri
BaseAddress = new Uri("http://localhost:131/"); public ActionResult Index() {
Client.BaseAddress = BaseAddress; HttpResponseMessage response =
Client.GetAsync("productservice/GetProducts").Result; if (response.IsSuccessStatusCode) { var
data = response.Content.ReadAsAsync<IEnumerable<Product>>().Result; return View(data); }
return View(); } }
DOT NET TRICKS TRAINING CENTER
B 64, Near SBI Bank, Sector 2 Noida, Metro Noida Sector 15, Uttar Pradesh (India)
www.dotnet-tricks.com, www.dotnettricks.com +91 98 71 749695, +91 120 426 5198
Page84
Training Highlights
Learn from qualified and experienced professional
Small batches to ensure personal attention
Hands-on real application development
Recorded session of your class
Training course material
Prepare yourself for interview and get great jobs
---------------------------------------------------------------------------------------------------------------------------

Routing:
Aaaaa

Q13. How ASP.NET WEB API routing is different from ASP.NET MVC routing?
Ans. ASP.NET MVC and ASP.NET WEB API both use routing to monitor incoming request and
at least one route is defined in order to function. The difference between these two routing is
given below:
1. In WEB API route pattern {action} parameter is optional but you can include an {action}
parameter. In ASP.NET MVC {action} parameter is mandatory.
2. The action methods defined in the API controller must either have the HTTP action verbs
(GET, POST, PUT, DELETE) attribute or have one of the HTTP action verbs as a prefix for the
actions methods name. In ASP.NET MVC, by default an action method can be called by HTTP
GET or POST verbs and for using others HTTP verbs you need to defined as an attribute.
3. Unlike ASP.NET MVC, Web API can receive only one complex type as a parameter.

Q14. How to enable Attribute Routing in ASP.NET WEB API2?


Ans. Enabling attribute routing in your ASP.NET WEB API2 is simple, just add a call to
MapHttpAttributeRoutes() method with in Register() method of WebApiConfig.cs file. public
static class WebApiConfig { public static void Register(HttpConfiguration config) { //enabling
attribute routing config.MapHttpAttributeRoutes(); } }
You can also combine attribute routing with convention-based routing. public static class
WebApiConfig { public static void Register(HttpConfiguration config) { //enabling attribute routing
config.MapHttpAttributeRoutes(); // Convention-based routing. config.Routes.MapHttpRoute(
name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id =
RouteParameter.Optional } ); } }

Q15. How to define attribute routing in ASP.NET WEB API2?


Ans. Like ASP.NET MVC5, you can also define attribute routing in WEB API2 at controller level
and action level as shown below:
DOT NET TRICKS TRAINING CENTER
B 64, Near SBI Bank, Sector 2 Noida, Metro Noida Sector 15, Uttar Pradesh (India)
www.dotnet-tricks.com, www.dotnettricks.com +91 98 71 749695, +91 120 426 5198
Page85
Training Highlights
Learn from qualified and experienced professional
Small batches to ensure personal attention
Hands-on real application development
Recorded session of your class
Training course material
Prepare yourself for interview and get great jobs
1. Controller level routing – You can define routes at controller level which apply to all actions
within the controller unless a specific route is added to an action. [RoutePrefix("Service/User")]
public class UserController : ApiController { //GET route: api/User public IEnumerable<string>
Get() { return new string[] { "value1", "value2" }; } [Route("{id}")] //GET route: Service/User/1
public string Get(int id) { return "value"; } [Route("")] //POST route: Service/User/ public void
Post([FromBody]string value) { } }
2. Action level routing – You can define routes at action level which apply to a specific action
with in the controller. public class UserController : ApiController { //GET route: api/User public
IEnumerable<string> Get() { return new string[] { "value1", "value2" }; }
[Route("Service/User/{id}")] //GET route: Service/User/1 public string Get(int id) { return "value";
} [Route("Service/User/")] //POST route: Service/User/ public void Post([FromBody]string value)
{}}
DOT NET TRICKS TRAINING CENTER
B 64, Near SBI Bank, Sector 2 Noida, Metro Noida Sector 15, Uttar Pradesh (India)
---------------------------------------------------------------------------------------------------------------------

Swatch QA Web API

http://www.dotnet-tricks.com/Tutorial/webapi/VG9K040413-What-is-Web-API-and-why-to-use-it-
?.html

-- WebAPI
1. What is web API, why we u How to create and how to consume using server side and ajaxse
what is use it.
2. advantages over others
3. verbs
4. Routing
5. token/authorazation and authontication
6. Cors baisc token authentication
7. How to create and how to consume using server side and ajax.
8. What is RestFull

What is Web API and why to use it ?


Asp.Net Web API is a framework for building HTTP services that can be consumed by a broad
range of clients including browsers, mobiles, iphone and tablets. It is very similar to ASP.NET
MVC since it contains the MVC features such as routing, controllers, action results, filter, model
binders, IOC container or dependency injection. But it is not a part of the MVC Framework. It is
a part of the core ASP.NET platform and can be used with MVC and other types of Web
applications like Asp.Net WebForms. It can also be used as an stand-alone Web services
application.

Why Asp.Net Web API (Web API) ?


Today, a web-based application is not enough to reach it's customers. People are very smart,
they are using iphone, mobile, tablets etc. devices in its daily life. These devices also have a lot
of apps for making the life easy. Actually, we are moving from the web towards apps world.
So, if you like to expose your service data to the browsers and as well as all these modern
devices apps in fast and simple way, you should have an API which is compatible with browsers
and all these devices.
For example twitter,facebook and Google API for the web application and phone apps.

Web API is the great framework for exposing your data and service to different-different
devices. Moreover Web API is open source an ideal platform for building REST-ful services over
the .NET Framework. Unlike WCF Rest service, it use the full featues of HTTP (like URIs,
request/response headers, caching, versioning, various content formats) and you don't need to
define any extra config settings for different devices unlike WCF Rest service.
Web API Features
It supports convention-based CRUD Actions since it works with HTTP verbs GET,POST,PUT
and DELETE.
Responses have an Accept header and HTTP status code.
Responses are formatted by Web API’s MediaTypeFormatter into JSON, XML or whatever
format you want to add as a MediaTypeFormatter.
It may accepts and generates the content which may not be object oriented like images, PDF
files etc.
It has automatic support for OData. Hence by placing the new [Queryable] attribute on a
controller method that returns IQueryable, clients can use the method for OData query
composition.
It can be hosted with in the applicaion or on IIS.
It also supports the MVC features such as routing, controllers, action results, filter, model
binders, IOC container or dependency injection that makes it more simple and robust.

Why to choose Web API ?


If we need a Web Service and don’t need SOAP, then ASP.Net Web API is best choice.
It is Used to build simple, non-SOAP-based HTTP Services on top of existing WCF message
pipeline.
It doesn't have tedious and extensive configuration like WCF REST service.
Simple service creation with Web API. With WCF REST Services, service creation is difficult.
It is only based on HTTP and easy to define, expose and consume in a REST-ful way.
It is light weight architecture and good for devices which have limited bandwidth like smart
phones.
It is open source.
-------------------------------------------------------------------------------------------------------------

WCF and Web API and WCF REST and Web Service
The .Net framework has a number of technologies that allow you to create HTTP services such
as Web Service, WCF and now Web API. There are a lot of articles over the internet which may
describe to whom you should use. Now a days, you have a lot of choices to build HTTP services
on .NET framework. In this article, I would like to share my opinion with you over Web Service,
WCF and now Web API. For more information about Web API refers

What is Web API and why to use it ?.


Web Service
It is based on SOAP and return data in XML form.
It support only HTTP protocol.
It is not open source but can be consumed by any client that understands xml.
It can be hosted only on IIS.
WCF
It is also based on SOAP and return data in XML form.
It is the evolution of the web service(ASMX) and support various protocols like TCP, HTTP,
HTTPS, Named Pipes, MSMQ.
The main issue with WCF is, its tedious and extensive configuration.
It is not open source but can be consumed by any client that understands xml.
It can be hosted with in the applicaion or on IIS or using window service.
WCF Rest
To use WCF as WCF Rest service you have to enable webHttpBindings.
It support HTTP GET and POST verbs by [WebGet] and [WebInvoke] attributes respectively.
To enable other HTTP verbs you have to do some configuration in IIS to accept request of that
particular verb on .svc files
Passing data through parameters using a WebGet needs configuration. The UriTemplate must
be specified
It support XML, JSON and ATOM data format.
Web API
This is the new framework for building HTTP services with easy and simple way.
Web API is open source an ideal platform for building REST-ful services over the .NET
Framework.
Unlike WCF Rest service, it use the full featues of HTTP (like URIs, request/response headers,
caching, versioning, various content formats)
It also supports the MVC features such as routing, controllers, action results, filter, model
binders, IOC container or dependency injection, unit testing that makes it more simple and
robust.
It can be hosted with in the application or on IIS.
It is light weight architecture and good for devices which have limited bandwidth like smart
phones.
Responses are formatted by Web API’s MediaTypeFormatter into JSON, XML or whatever
format you want to add as a MediaTypeFormatter.

To whom choose between WCF or WEB API


Choose WCF when you want to create a service that should support special scenarios such as
one way messaging, message queues, duplex communication etc.
Choose WCF when you want to create a service that can use fast transport channels when
available, such as TCP, Named Pipes, or maybe even UDP (in WCF 4.5), and you also want to
support HTTP when all other transport channels are unavailable.
Choose Web API when you want to create a resource-oriented services over HTTP that can use
the full features of HTTP (like URIs, request/response headers, caching, versioning, various
content formats).
Choose Web API when you want to expose your service to a broad range of clients including
browsers, mobiles, iphone and tablets.
What do you think?
I hope, you have got when to use WCF, Web API and Web Service. I would like to have
feedback from my blog readers. Your valuable feedback, question, or comments about this
article are always welcome.
-------------------------------------------------------------------------------------------------------------

ASP.NET MVC and ASP.NET Web API


While developing your web application using MVC, many developers got confused when to use
Web API, since MVC framework can also return JSON data by using JsonResult and can also
handle simple AJAX requests. In previous article, I have explained the Difference between WCF
and Web API and WCF REST and Web Service and when to use Web API over others services.
In this article, you will learn when to use Web API with MVC.

Asp.Net Web API VS Asp.Net MVC


Asp.Net MVC is used to create web applications that returns both views and data but Asp.Net
Web API is used to create full blown HTTP services with easy and simple way that returns only
data not view.
Web API helps to build REST-ful services over the .NET Framework and it also support
content-negotiation(it's about deciding the best response format data that could be acceptable
by the client. it could be JSON,XML,ATOM or other formatted data), self hosting which are not in
MVC.
Web API also takes care of returning data in particular format like JSON,XML or any other
based upon the Accept header in the request and you don't worry about that. MVC only return
data in JSON format using JsonResult.
In Web API the request are mapped to the actions based on HTTP verbs but in MVC it is
mapped to actions name.
Asp.Net Web API is new framework and part of the core ASP.NET framework. The model
binding, filters, routing and others MVC features exist in Web API are different from MVC and
exists in the new System.Web.Http assembly. In MVC, these featues exist with in
System.Web.Mvc. Hence Web API can also be used with Asp.Net and as a stand alone service
layer.
You can mix Web API and MVC controller in a single project to handle advanced AJAX requests
which may return data in JSON, XML or any others format and building a full blown HTTP
service. Typically, this will be called Web API self hosting.
When you have mixed MVC and Web API controller and you want to implement the
authorization then you have to create two filters one for MVC and another for Web API since
boths are different.
Moreover, Web API is light weight architecture and except the web application it can also be
used with smart phone apps.
-------------------------------------------------------------------------------------------------------------

Pass javascript complex object to ASP.NET Web Api and MVC


ASP.NET Web API is one of the most powerful recent addition to ASP.NET framework.
Sometimes, you have to post a form data using jQuery-JSON to Web API or MVC method,
which have so many input fields. Passing each and every input field data as a separate
parameter is not good practice, even when you have a strongly typed-view. The best practice is,
pass a complex type object for all the input fields to the server side to remove complexity.
-------------------------------------------------------------------------------------------------------------

Comparing Asp.Net Web API Routing and Asp.Net MVC Routing

As you know, Routing is a pattern matching system that monitor the incoming request and figure
out what to do with that request. A URL pattern is matched against the routes patterns defined
in the Route dictionary in an Order and the first match wins. This means the first route which
successfully matches a controller, action, and action parameters defined in the URL will call into
the specified controller and action.
Asp.Net MVC application and Asp.Net Web API must have at least one route defined in order to
function. Hence, Visual Studio templates defined for MVC and Web API must have a default
route. Now let's understand the difference between Asp.Net MVC and Asp.Net Web API.
Default Route Pattern
The default route pattern for a Web API Project is defined as follows-
config.Routes.MapHttpRoute(
name: "DefaultApi", //route name
routeTemplate: "api/{controller}/{id}", //route pattern
defaults: new { id = RouteParameter.Optional } //parameter default values
);
The literal api at the beginning of the Web API route pattern, makes it distinct from the standard
MVC route. This is not mandatory but it is a good convention to differ Web API route from MVC
route.
In Web API route pattern {action} parameter is optional but you can include an {action}
parameter. Also, the action methods defined on the controller must be have an HTTP action
verb as a prefix to the method name in order to work. So, you can also define the route for Web
API as follows-
config.Routes.MapHttpRoute(
name: "DefaultApi",//route name
routeTemplate: "api/{controller}/{action}/{id}",//route pattern
defaults: new { id = RouteParameter.Optional }//parameter default values
);
The default route pattern for an Asp.Net MVC Project is defined as follows-
routes.MapRoute(
name: "Default", //route name
url: "{controller}/{action}/{id}", //route pattern
defaults: new
{
controller = "Home",
action = "Index",
id = UrlParameter.Optional
} //parameter default values
);
As you have seen there is no literal before at the beginning of the Asp.Net MVC route pattern
but you can add if you wish.
Route Processing
In Web API route processing the URLs map to a controller, and then to the action which
matches the HTTP verb of the request and the most parameters of the request is selected. The
Action methods defined in the API controller must either have the HTTP action verbs (GET,
POST, PUT, DELETE) or have one of the HTTP action verbs as a prefix for the Actions
methods name as given below-
public class ValuesController : ApiController
{
// GET api/
public IEnumerable Get()
{
return new string[] { "value1", "value2" };
}
// GET api//5
public string Get(int id)
{
return "value";
}
// POST api/
public void Post([FromBody]string value)
{
}
// PUT api//5
public void Put(int id, [FromBody]string value)
{
}
// DELETE api//5
public void Delete(int id)
{
}
}
// OR You can also defined above API Controller as Verb Prefix
public class ValuesController : ApiController
{
// GET api/values
public IEnumerable GetValues()
{
return new string[] { "value1", "value2" };
}
// GET api/values/5
public string GetValues(int id)
{
return "value";
}
// POST api/values
public void PostValues([FromBody]string value)
{
}
// PUT api/values/5
public void PutValues(int id, [FromBody]string value)
{
}
// DELETE api/values/5
public void DeleteValues(int id)
{
}
}
In Asp.Net MVC route processing the URLs map to a controller, and then to the action which
matches the HTTP verb of the request and the most parameters of the request is selected. The
Action methods defined in the MVC controller do not have HTTP action verbs as a prefix for the
Actions methods but they have name like as normal method as shown below-
public class HomeController : Controller
{
// GET: /Home/Index
public ActionResult Index() //method - Index
{
// To Do:
return View();
}

// Post: /Home/Index
[HttpPost]
public ActionResult Index(LoginModel model, string id)
{
// To Do:
return View();
}
}
In MVC, by default HTTP verb is GET for using others HTTP verbs you need defined as an
attribute but in Web API you need to define as an method's name prefix.
-------------------------------------------------------------------------------------------------------------
Verbs:

List

Post
The POST verb is most-often utilized to **create** new resources. In particular, it's used to
create subordinate resources. That is, subordinate to some other (e.g. parent) resource. In other
words, when creating a new resource, POST to the parent and the service takes care of
associating the new resource with the parent, assigning an ID (new resource URI), etc.
On successful creation, return HTTP status 201, returning a Location header with a link to the
newly-created resource with the 201 HTTP status.
POST is neither safe nor idempotent. It is therefore recommended for non-idempotent resource
requests. Making two identical POST requests will most-likely result in two resources containing
the same information.

Get
The HTTP GET method is used to **read** (or retrieve) a representation of a resource. In the
“happy” (or non-error) path, GET returns a representation in XML or JSON and an HTTP
response code of 200 (OK). In an error case, it most often returns a 404 (NOT FOUND) or 400
(BAD REQUEST).
According to the design of the HTTP specification, GET (along with HEAD) requests are used
only to read data and not change it. Therefore, when used this way, they are considered safe.
That is, they can be called without risk of data modification or corruption—calling it once has the
same effect as calling it 10 times, or none at all. Additionally, GET (and HEAD) is idempotent,
which means that making multiple identical requests ends up having the same result as a single
request.
Do not expose unsafe operations via GET—it should never modify any resources on the server.

PUT
PUT is most-often utilized for **update** capabilities, PUT-ing to a known resource URI with the
request body containing the newly-updated representation of the original resource.
However, PUT can also be used to create a resource in the case where the resource ID is
chosen by the client instead of by the server. In other words, if the PUT is to a URI that contains
the value of a non-existent resource ID. Again, the request body contains a resource
representation. Many feel this is convoluted and confusing. Consequently, this method of
creation should be used sparingly, if at all.
Alternatively, use POST to create new resources and provide the client-defined ID in the body
representation—presumably to a URI that doesn't include the ID of the resource (see POST
below).
On successful update, return 200 (or 204 if not returning any content in the body) from a PUT. If
using PUT for create, return HTTP status 201 on successful creation. A body in the response is
optional—providing one consumes more bandwidth. It is not necessary to return a link via a
Location header in the creation case since the client already set the resource ID.
PUT is not a safe operation, in that it modifies (or creates) state on the server, but it is
idempotent. In other words, if you create or update a resource using PUT and then make that
same call again, the resource is still there and still has the same state as it did with the first call.
If, for instance, calling PUT on a resource increments a counter within the resource, the call is
no longer idempotent. Sometimes that happens and it may be enough to document that the call
is not idempotent. However, it's recommended to keep PUT requests idempotent. It is strongly
recommended to use POST for non-idempotent requests.

PATCH
PATCH is used for **modify** capabilities. The PATCH request only needs to contain the
changes to the resource, not the complete resource.
This resembles PUT, but the body contains a set of instructions describing how a resource
currently residing on the server should be modified to produce a new version. This means that
the PATCH body should not just be a modified part of the resource, but in some kind of patch
language like JSON Patch or XML Patch.
PATCH is neither safe nor idempotent. However, a PATCH request can be issued in such a way
as to be idempotent, which also helps prevent bad outcomes from collisions between two
PATCH requests on the same resource in a similar time frame. Collisions from multiple PATCH
requests may be more dangerous than PUT collisions because some patch formats need to
operate from a known base-point or else they will corrupt the resource. Clients using this kind of
patch application should use a conditional request such that the request will fail if the resource
has been updated since the client last accessed the resource. For example, the client can use a
strong ETag in an If-Match header on the PATCH request.

DELETE
DELETE is pretty easy to understand. It is used to **delete** a resource identified by a URI.
On successful deletion, return HTTP status 200 (OK) along with a response body, perhaps the
representation of the deleted item (often demands too much bandwidth), or a wrapped response
(see Return Values below). Either that or return HTTP status 204 (NO CONTENT) with no
response body. In other words, a 204 status with no body, or the JSEND-style response and
HTTP status 200 are the recommended responses.
HTTP-spec-wise, DELETE operations are idempotent. If you DELETE a resource, it's removed.
Repeatedly calling DELETE on that resource ends up the same: the resource is gone. If calling
DELETE say, decrements a counter (within the resource), the DELETE call is no longer
idempotent. As mentioned previously, usage statistics and measurements may be updated
while still considering the service idempotent as long as no resource data is changed. Using
POST for non-idempotent resource requests is recommended.
There is a caveat about DELETE idempotence, however. Calling DELETE on a resource a
second time will often return a 404 (NOT FOUND) since it was already removed and therefore is
no longer findable. This, by some opinions, makes DELETE operations no longer idempotent,
however, the end-state of the resource is the same. Returning a 404 is acceptable and
communicates accurately the status of the call.
------------------

Following up after the earlier post titled Using HTTP Status Codes correctly in your REST Web
API, here is one on using the HTTP Verbs from the W3C spec in the "right way" to have a clean
REST Web API. Just like the HTTP status codes, there are many more verbs in the HTTP
standard that, although they are in theory OK to use for your Web API, you can get by with just
a few that helps to keep your API simple, and self-explanatory to its clients.

The full list of HTTP verbs from the spec can be found HERE, but we are going to focus on how
to interpret the verbs and the actions that should be executed for each on in the context of a
well-defined REST Web API. In the table there is also the result set that standard clients expect
when they make requests with such VERBs. To better understand their proper use, we'll use a
sample resource endpoint called Users, where the (you guessed it) "Users" of our app are
exposed via our Web API.

Resource Sample GET (aka Read) POST (aka insert) PUT (aka update)
DELETE (aka delete) PATCH (aka partial update)
api/users Action Gets a list of users Creates a user Batch Update Errors out
Batch Update the users only with the attributes present in the request
Return List of users New user No payload, only HTTP Status Code Error HTTP Status
Code No payload, only HTTP Status Code
api/users/123 Action Gets a single user Errors out Updates the user Deletes the
user Partially updates the user only with the attributes present in the request
Return Single user Error HTTP Status Code Updated user No payload, only HTTP
Status Code Updated full user object
-------------

Using HTTP Methods (GET, POST, PUT, etc.) in Web API


December 6th, 2015
asp.net · tutorials · web-api · http
My group has been studying ASP.NET Web API for a major project we're working on, and part
of learning about this tech stack is studying how HTTP works, which has been a nice refresher
for us. A couple of my teammates asked me to clarify the HTTP Methods (e.g. GET, POST,
PUT, DELETE, etc) we were going to use for specific actions, and I wanted to learn more about
them. Hence, this post. Come along with us as we learn about HTTP methods (also called
verbs) and discuss how and when to use them in our Web API projects!

What Are HTTP Methods?

Whenever a client submits a request to a server, part of that request is an HTTP method, which
is what the client would like the server to do with the specified resource. HTTP methods
represent those requested actions. For example, some commonly-used HTTP methods will
retrieve data from a server, submit data to a server for processing, delete an item from the
server's data store, etc. For a more general overview of HTTP, see Tutorials Point's article.

Selecting The Appropriate Method

A large portion of application functionality can be summed up in the acronym CRUD, which
stands for Create, Read, Update, Delete. There are four HTTP methods that correspond to
these actions, one for each, like so:

C - Create - POST
R - Read - GET
U - Update - PUT
D - Delete - DELETE

So, in a given app, you might have the following action:

public IHttpActionResult Add(string title)


{
//Creates a Movie based on the Title
return Ok();
}
We can tell from the name of the action (and, let's be real, the comment) that this action is
supposed to create a movie. So we should use the POST verb on this action, like so:

[HttpPost]
public IHttpActionResult Add(string title)
{
//Creates a Movie based on the Title
return Ok();
}
If you need a particular action to support more than one HTTP method, you can use the
[AcceptVerbs] attribute:

[AcceptVerbs("POST", "PUT")]
public IHttpActionResult Add(string title)
{
//Creates a Movie based on the Title
return Ok();
}
For the majority of applications, GET, POST, PUT, and DELETE should be all the HTTP
methods you need to use. However, there are a few other methods we could utilize if the need
arises.

HEAD: This is identical to a GET request, but only returns the headers for the response, not the
response body. Theoretically faster, commonly used for checking to see if a particular resources
exists or can be accessed.
OPTIONS: Returns the HTTP methods supported by the server for the specified URL.
PATCH: Submits a partial modification to a resource. If you only need to update one field for the
resource, you may want to use the PATCH method.
POST vs PUT

POST and PUT are very similar in that they both send data to the server that the server will
need to store somewhere. Technically speaking, you could use either for the Create or Update
scenarios, and in fact this is rather common. The difference lies in the details.

PUT is idempotent. What this means is that if you make the same request twice using PUT, with
the same parameters both times, the second request will have no effect. This is why PUT is
generally used for the Update scenario; calling Update more than once with the same
parameters doesn't do anything more than the first call did.

By contrast, POST is not idempotent; making the same call using POST with same parameters
each time will cause two different things to happen, hence why POST is commonly used for the
Create scenario (submitting two identical items to a Create method should create two entries in
the data store).
(It should be noted that, strictly speaking, HTTP does not force PUT to be idempotent, so you
can implement your server to use PUT in a non-idempotent way. However, doing so is liable to
cause a horde of angry server admins to show up at your desk and beat you with ethernet
cables. Don't say I didn't warn you.)

Default HTTP Methods

If we do not assign an explicit HTTP method to a controller action, what method(s) does that
action accept? Let's imagine we have a Web API controller like so:

public class MovieController : ApiController


{
/// <summary>
/// Returns all movies.
/// </summary>
/// <returns>A JSON list of all movies.</returns>
[Route("movies/all")]
public IHttpActionResult All()
{
List<Movie> movies = new List<Movie>()
{
new Movie()
{
Id = 1,
Title = "Up",
ReleaseDate = new DateTime(2009,5,29),
RunningTimeMinutes = 96
},
new Movie()
{
Id = 2,
Title = "Toy Story",
ReleaseDate = new DateTime(1995, 11, 19),
RunningTimeMinutes = 81
},
new Movie()
{
Id = 3,
Title = "Big Hero 6",
ReleaseDate = new DateTime(2014, 11, 7),
RunningTimeMinutes = 102
}
};

return Ok(movies);
}
}
We can tell by looking at the code that this should be a GET action, since it is returning data.
However, we're not explicitly saying that GET should be used (there's no [HttpGet] attribute).
So, what method(s) will this action accept? Let's see what Postman can tell us.

It should be a GET action, so let's try to hit this action with a GET request.

Well, that didn't work, we get back a 405 Method Not Allowed status. Why were we not able to
use the GET method?

The algorithm ASP.NET uses to calculate the "default" method for a given action goes like this:

If there is an attribute applied (via [HttpGet], [HttpPost], [HttpPut], [AcceptVerbs], etc), the action
will accept the specified HTTP method(s).
If the name of the controller action starts the words "Get", "Post", "Put", "Delete", "Patch",
"Options", or "Head", use the corresponding HTTP method.
Otherwise, the action supports the POST method.
We're falling in to the #3 condition here: the action name All() doesn't contain any of the key
words and we didn't specify an action, so this action will only support POST. Sure enough,
guess what Postman shows for a POST action?

Obviously, this is not what we want. We're getting data from the server using a POST method,
and this (while not technologically prevented) is not what these HTTP methods were designed
for.

We could solve this problem in two ways. The first would be to add the [HttpGet] attribute to the
method. The second would be to rename the method to GetAll(); the existence of the word "Get"
at the start of the method tells ASP.NET to accept a GET HTTP method on this action. My
personal preference is to always explicitly state which HTTP method is accepted by any action,
like so:

public class MovieController : ApiController


{
/// <summary>
/// Returns all movies.
/// </summary>
/// <returns>A JSON list of all movies.</returns>
[Route("movies/all")]
[HttpGet] //Always explicitly state the accepted HTTP method
public IHttpActionResult All()
{
//Get movies
return Ok(movies);
}
}

-------------------------------------------------------------------------------------------------------------

What is REST?
REST stands for Representational state transfer which essentially refers to a style of web
architecture that has many underlying characteristics and governs the behavior of clients and
servers.

What can use a REST API?


REST API lets you interact with Parse from anything that can send an HTTP request. See Parse
REST Definition for examples of this.

What is meant by the term “RESTful API”?


Conforming to the REST constraints is generally referred to as being “RESTful”
An API can be considered “RESTful” if it has the following features (not a complete list just the
main ones):
Client–server – The client handles the front end the server handles the backend and can both
be replaced independently of each other.
Stateless – No client data is stored on the server between requests and session state is stored
on the client.
Cacheable – Clients can cache response (just like browsers caching static elements of a web
page) to improve performance.
Complying with these constraints, and thus conforming to the REST architectural style enables
any kind of distributed hypermedia system to have desirable emergent properties, such as
performance, scalability, simplicity, modifiability, visibility, portability, and reliability. A common
trend I have seen is to use absolute urls for RESTful APIs which are meaningful.

What is REST ?
REST stands for REpresentational State Transfer. REST is web standards based architecture
and uses HTTP Protocol for data communication. It revolves around resource where every
component is a resource and a resource is accessed by a common interface using HTTP
standard methods. REST was first introduced by Roy Fielding in 2000.
In REST architecture, a REST Server simply provides access to resources and REST client
accesses and presents the resources. Here each resource is identified by URIs/ global IDs.
REST uses various representations to represent a resource like text, JSON and XML. Now a
days JSON is the most popular format being used in web services.

HTTP Methods
Following well known HTTP methods are commonly used in REST based architecture.
GET - Provides a read only access to a resource.
PUT - Used to create a new resource.
DELETE - Used to remove a resource.
POST - Used to update a existing resource or create a new resource.
OPTIONS - Used to get the supported operations on a resource.

RESTFul Web Services


A web service is a collection of open protocols and standards used for exchanging data
between applications or systems. Software applications written in various programming
languages and running on various platforms can use web services to exchange data over
computer networks like the Internet in a manner similar to inter-process communication on a
single computer. This interoperability (e.g., between Java and Python, or Windows and Linux
applications) is due to the use of open standards.
Web services based on REST Architecture are known as RESTful web services. These web
services use HTTP methods to implement the concept of REST architecture. A RESTful web
service usually defines a URI, Uniform Resource Identifier a service, provides resource
representation such as JSON and set of HTTP Methods.
Creating RESTFul Web Service
Sr. No. HTTP Method URI Operation Operation Type
1 GET /UserService/users Get list of users Read Only
2 GET /UserService/users/1 Get User with Id 1 Read Only
3 PUT /UserService/users/2 Insert User with Id 2 Idempotent
4 POST /UserService/users/2 Update User with Id 2 N/A
5 DELETE /UserService/users/1 Delete User with Id 1 Idempotent
6 OPTIONS /UserService/users List the supported operations in web service Read
Only

The “RESTful” Client Server Architecture


HTTP, for example, has a very rich vocabulary in terms of verbs (or “methods”), URIs, Internet
media types, request and response codes, etc. REST uses these existing features of the HTTP
protocol, and thus allows existing layered proxy and gateway components to perform additional
functions on the network such as HTTP caching and security enforcement.

RESTful Web Services (API)


A RESTful web service (also called a RESTful web API) is a web service implemented using
HTTP and the principles of REST. It is a collection of resources, with four defined aspects:
the base URI for the web service, such as http://example.com/resources/

the Internet media type of the data supported by the web service. This is often XML but can be
any other valid Internet media type provided that it is a valid hypertext standard.
the set of operations supported by the web service using HTTP methods (e.g., GET, PUT,
POST, or DELETE).

It is a collection of resources, with four defined aspects:


the base URI for the web service, such as http://example.com/resources/
the Internet media type of the data supported by the web service. This is often JSON, XML or
YAML but can be any other valid Internet media type.
the set of operations supported by the web service using HTTP methods (e.g., POST, GET,
PUT or DELETE).
The API must be hypertext driven.[11]
Popular REST API Request Formats
REST
XML-RPC
SOAP
Also see: The Main Differences Between SOAP and REST APIs

Popular REST API Response Formats


I work mostly with JSON it seems to be the most popular for jQuery developers, for obvious
reasons.

Do I need an API key to access a REST API?


Most API’s have a request limit and might ask you to provide an API key (which you may have
created an application with them). Data sensitive APIs will require you to authenticate and the
most popular method is Open Authentication also known as oAuth. I’ve touched briefly on this
before on How Twitter oAuth works. Won’t go into oAuth here.

Example is Google Translate requires your API Key in a GET request.


https://www.googleapis.com/language/translate/v2?key=INSERT-YOUR-KEY&source=en&targe
t=de&q=Hello%20world
So is it a REST API or just an API?
Well to decide this you will have to stufy the documentation and determine if the API satisfies
the criterion to qualify it to be RESTful. The Atom API is a good example of one that truely
qualifies it to be RESTful.
-----------------------------------------------------------------------------------------------------------
Authentication & Authorization

http://www.codeproject.com/Articles/1005485/RESTful-Day-sharp-Security-in-Web-APIs-Basic
-----------------------------------------------------------------------------------------------------------
Routing

Routing in ASP.NET Web API

This article describes how ASP.NET Web API routes HTTP requests to controllers.

If you are familiar with ASP.NET MVC, Web API routing is very similar to MVC routing. The
main difference is that Web API uses the HTTP method, not the URI path, to select the action.
You can also use MVC-style routing in Web API. This article does not assume any knowledge of
ASP.NET MVC.

Routing Tables

In ASP.NET Web API, a controller is a class that handles HTTP requests. The public methods
of the controller are called action methods or simply actions. When the Web API framework
receives a request, it routes the request to an action.

To determine which action to invoke, the framework uses a routing table. The Visual Studio
project template for Web API creates a default route:

routes.MapHttpRoute(
name: "API Default",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
This route is defined in the WebApiConfig.cs file, which is placed in the App_Start directory:

For more information aboout the WebApiConfig class, see Configuring ASP.NET Web API .

If you self-host Web API, you must set the routing table directly on the
HttpSelfHostConfiguration object. For more information, see Self-Host a Web API.

Each entry in the routing table contains a route template. The default route template for Web
API is "api/{controller}/{id}". In this template, "api" is a literal path segment, and {controller} and
{id} are placeholder variables.

When the Web API framework receives an HTTP request, it tries to match the URI against one
of the route templates in the routing table. If no route matches, the client receives a 404 error.
For example, the following URIs match the default route:
/api/contacts
/api/contacts/1
/api/products/gizmo1
However, the following URI does not match, because it lacks the "api" segment:

/contacts/1
Note: The reason for using "api" in the route is to avoid collisions with ASP.NET MVC routing.
That way, you can have "/contacts" go to an MVC controller, and "/api/contacts" go to a Web
API controller. Of course, if you don't like this convention, you can change the default route
table.

Once a matching route is found, Web API selects the controller and the action:

To find the controller, Web API adds "Controller" to the value of the {controller} variable.
To find the action, Web API looks at the HTTP method, and then looks for an action whose
name begins with that HTTP method name. For example, with a GET request, Web API looks
for an action that starts with "Get...", such as "GetContact" or "GetAllContacts". This convention
applies only to GET, POST, PUT, and DELETE methods. You can enable other HTTP methods
by using attributes on your controller. We’ll see an example of that later.
Other placeholder variables in the route template, such as {id}, are mapped to action
parameters.
Let's look at an example. Suppose that you define the following controller:

public class ProductsController : ApiController


{
public void GetAllProducts() { }
public IEnumerable<Product> GetProductById(int id) { }
public HttpResponseMessage DeleteProduct(int id){ }
}
Here are some possible HTTP requests, along with the action that gets invoked for each:

HTTP Method URI Path Action Parameter


GET api/products GetAllProducts (none)
GET api/products/4 GetProductById 4
DELETE api/products/4 DeleteProduct 4
POST api/products (no match)
Notice that the {id} segment of the URI, if present, is mapped to the id parameter of the action.
In this example, the controller defines two GET methods, one with an id parameter and one with
no parameters.

Also, note that the POST request will fail, because the controller does not define a "Post..."
method.
Routing Variations

The previous section described the basic routing mechanism for ASP.NET Web API. This
section describes some variations.

HTTP Methods

Instead of using the naming convention for HTTP methods, you can explicitly specify the HTTP
method for an action by decorating the action method with the HttpGet, HttpPut, HttpPost, or
HttpDelete attribute.

In the following example, the FindProduct method is mapped to GET requests:

public class ProductsController : ApiController


{
[HttpGet]
public Product FindProduct(id) {}
}
To allow multiple HTTP methods for an action, or to allow HTTP methods other than GET, PUT,
POST, and DELETE, use the AcceptVerbs attribute, which takes a list of HTTP methods.

public class ProductsController : ApiController


{
[AcceptVerbs("GET", "HEAD")]
public Product FindProduct(id) { }

// WebDAV method
[AcceptVerbs("MKCOL")]
public void MakeCollection() { }
}

Routing by Action Name​With the default routing template, Web API uses the HTTP method to
select the action. However, you can also create a route where the action name is included in the
URI:

routes.MapHttpRoute(
name: "ActionApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
In this route template, the {action} parameter names the action method on the controller. With
this style of routing, use attributes to specify the allowed HTTP methods. For example, suppose
your controller has the following method:

public class ProductsController : ApiController


{
[HttpGet]
public string Details(int id);
}
In this case, a GET request for “api/products/details/1” would map to the Details method. This
style of routing is similar to ASP.NET MVC, and may be appropriate for an RPC-style API.

You can override the action name by using the ActionName attribute. In the following example,
there are two actions that map to "api/products/thumbnail/id. One supports GET and the other
supports POST:

public class ProductsController : ApiController


{
[HttpGet]
[ActionName("Thumbnail")]
public HttpResponseMessage GetThumbnailImage(int id);

[HttpPost]
[ActionName("Thumbnail")]
public void AddThumbnailImage(int id);
}

Non-Actions

To prevent a method from getting invoked as an action, use the NonAction attribute. This
signals to the framework that the method is not an action, even if it would otherwise match the
routing rules.

// Not an action method.


[NonAction]
public string GetPrivateData() { ... }
----------------------
Routing and Action Selection in ASP.NET Web API
By Mike Wasson|July 27, 2012
502 of 536 people found this helpful
Print
This article describes how ASP.NET Web API routes an HTTP request to a particular action on
a controller.
For a high-level overview of routing, see Routing in ASP.NET Web API.

This article looks at the details of the routing process. If you create a Web API project and find
that some requests don’t get routed the way you expect, hopefully this article will help.

Routing has three main phases:

Matching the URI to a route template.


Selecting a controller.
Selecting an action.
You can replace some parts of the process with your own custom behaviors. In this article, I
describe the default behavior. At the end, I note the places where you can customize the
behavior.

Route Templates

A route template looks similar to a URI path, but it can have placeholder values, indicated with
curly braces:

"api/{controller}/public/{category}/{id}"
When you create a route, you can provide default values for some or all of the placeholders:

defaults: new { category = "all" }


You can also provide constraints, which restrict how a URI segment can match a placeholder:

constraints: new { id = @"\d+" } // Only matches if "id" is one or more digits.


The framework tries to match the segments in the URI path to the template. Literals in the
template must match exactly. A placeholder matches any value, unless you specify constraints.
The framework does not match other parts of the URI, such as the host name or the query
parameters. The framework selects the first route in the route table that matches the URI.

There are two special placeholders: "{controller}" and "{action}".

"{controller}" provides the name of the controller.


"{action}" provides the name of the action. In Web API, the usual convention is to omit "{action}".
Defaults

If you provide defaults, the route will match a URI that is missing those segments. For example:

routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{category}",
defaults: new { category = "all" }
);
The URI "http://localhost/api/products" matches this route. The "{category}" segment is assigned
the default value "all".

Route Dictionary

If the framework finds a match for a URI, it creates a dictionary that contains the value for each
placeholder. The keys are the placeholder names, not including the curly braces. The values
are taken from the URI path or from the defaults. The dictionary is stored in the IHttpRouteData
object.

During this route-matching phase, the special "{controller}" and "{action}" placeholders are
treated just like the other placeholders. They are simply stored in the dictionary with the other
values.

A default can have the special value RouteParameter.Optional. If a placeholder gets assigned
this value, the value is not added to the route dictionary. For example:

routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{category}/{id}",
defaults: new { category = "all", id = RouteParameter.Optional }
);
For the URI path "api/products", the route dictionary will contain:

controller: "products"
category: "all"
For "api/products/toys/123", however, the route dictionary will contain:

controller: "products"
category: "toys"
id: "123"
The defaults can also include a value that does not appear anywhere in the route template. If
the route matches, that value is stored in the dictionary. For example:

routes.MapHttpRoute(
name: "Root",
routeTemplate: "api/root/{id}",
defaults: new { controller = "customers", id = RouteParameter.Optional }
);
If the URI path is "api/root/8", the dictionary will contain two values:
controller: "customers"
id: "8"
Selecting a Controller

Controller selection is handled by the IHttpControllerSelector.SelectController method. This


method takes an HttpRequestMessage instance and returns an HttpControllerDescriptor. The
default implementation is provided by the DefaultHttpControllerSelector class. This class uses a
straightforward algorithm:

Look in the route dictionary for the key "controller".


Take the value for this key and append the string "Controller" to get the controller type name.
Look for a Web API controller with this type name.
For example, if the route dictionary contains the key-value pair "controller" = "products", then the
controller type is "ProductsController". If there is no matching type, or multiple matches, the
framework returns an error to the client.

For step 3, DefaultHttpControllerSelector uses the IHttpControllerTypeResolver interface to get


the list of Web API controller types. The default implementation of IHttpControllerTypeResolver
returns all public classes that (a) implement IHttpController, (b) are not abstract, and (c) have a
name that ends in "Controller".

Action Selection

After selecting the controller, the framework selects the action by calling the
IHttpActionSelector.SelectAction method. This method takes an HttpControllerContext and
returns an HttpActionDescriptor.

The default implementation is provided by the ApiControllerActionSelector class. To select an


action, it looks at the following:

The HTTP method of the request.


The "{action}" placeholder in the route template, if present.
The parameters of the actions on the controller.
Before looking at the selection algorithm, we need to understand some things about controller
actions.

Which methods on the controller are considered "actions"? When selecting an action, the
framework only looks at public instance methods on the controller. Also, it excludes "special
name" methods (constructors, events, operator overloads, and so forth), and methods inherited
from the ApiController class.

HTTP Methods. The framework only chooses actions that match the HTTP method of the
request, determined as follows:
You can specify the HTTP method with an attribute: AcceptVerbs, HttpDelete, HttpGet,
HttpHead, HttpOptions, HttpPatch, HttpPost, or HttpPut.
Otherwise, if the name of the controller method starts with "Get", "Post", "Put", "Delete", "Head",
"Options", or "Patch", then by convention the action supports that HTTP method.
If none of the above, the method supports POST.
Parameter Bindings. A parameter binding is how Web API creates a value for a parameter.
Here is the default rule for parameter binding:

Simple types are taken from the URI.


Complex types are taken from the request body.
Simple types include all of the .NET Framework primitive types, plus DateTime, Decimal, Guid,
String, and TimeSpan. For each action, at most one parameter can read the request body.

It is possible to override the default binding rules. See WebAPI Parameter binding under the
hood.

With that background, here is the action selection algorithm.

Create a list of all actions on the controller that match the HTTP request method.
If the route dictionary has an "action" entry, remove actions whose name does not match this
value.
Try to match action parameters to the URI, as follows:
For each action, get a list of the parameters that are a simple type, where the binding gets the
parameter from the URI. Exclude optional parameters.
From this list, try to find a match for each parameter name, either in the route dictionary or in the
URI query string. Matches are case insensitive and do not depend on the parameter order.
Select an action where every parameter in the list has a match in the URI.
If more that one action meets these criteria, pick the one with the most parameter matches.
Ignore actions with the [NonAction] attribute.
Step #3 is probably the most confusing. The basic idea is that a parameter can get its value
either from the URI, from the request body, or from a custom binding. For parameters that come
from the URI, we want to ensure that the URI actually contains a value for that parameter, either
in the path (via the route dictionary) or in the query string.

For example, consider the following action:

public void Get(int id)


The id parameter binds to the URI. Therefore, this action can only match a URI that contains a
value for "id", either in the route dictionary or in the query string.

Optional parameters are an exception, because they are optional. For an optional parameter, it's
OK if the binding can't get the value from the URI.
Complex types are an exception for a different reason. A complex type can only bind to the URI
through a custom binding. But in that case, the framework cannot know in advance whether the
parameter would bind to a particular URI. To find out, it would need to invoke the binding. The
goal of the selection algorithm is to select an action from the static description, before invoking
any bindings. Therefore, complex types are excluded from the matching algorithm.

After the action is selected, all parameter bindings are invoked.

Summary:

The action must match the HTTP method of the request.


The action name must match the "action" entry in the route dictionary, if present.
For every parameter of the action, if the parameter is taken from the URI, then the parameter
name must be found either in the route dictionary or in the URI query string. (Optional
parameters and parameters with complex types are excluded.)
Try to match the most number of parameters. The best match might be a method with no
parameters.
Extended Example

Routes:

routes.MapHttpRoute(
name: "ApiRoot",
routeTemplate: "api/root/{id}",
defaults: new { controller = "products", id = RouteParameter.Optional }
);
routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
Controller:

public class ProductsController : ApiController


{
public IEnumerable<Product> GetAll() {}
public Product GetById(int id, double version = 1.0) {}
[HttpGet]
public void FindProductsByName(string name) {}
public void Post(Product value) {}
public void Put(int id, Product value) {}
}
HTTP request:

GET http://localhost:34701/api/products/1?version=1.5&details=1
Route Matching

The URI matches the route named "DefaultApi". The route dictionary contains the following
entries:

controller: "products"
id: "1"
The route dictionary does not contain the query string parameters, "version" and "details", but
these will still be considered during action selection.

Controller Selection

From the "controller" entry in the route dictionary, the controller type is ProductsController.

Action Selection

The HTTP request is a GET request. The controller actions that support GET are GetAll,
GetById, and FindProductsByName. The route dictionary does not contain an entry for "action",
so we don’t need to match the action name.

Next, we try to match parameter names for the actions, looking only at the GET actions.

Action Parameters to Match


GetAll none
GetById "id"
FindProductsByName"name"
Notice that the version parameter of GetById is not considered, because it is an optional
parameter.

The GetAll method matches trivially. The GetById method also matches, because the route
dictionary contains "id". The FindProductsByName method does not match.

The GetById method wins, because it matches one parameter, versus no parameters for GetAll.
The method is invoked with the following parameter values:

id = 1
version = 1.5
Notice that even though version was not used in the selection algorithm, the value of the
parameter comes from the URI query string.
Extension Points

Web API provides extension points for some parts of the routing process.

Interface Description
IHttpControllerSelector Selects the controller.
IHttpControllerTypeResolver Gets the list of controller types. The DefaultHttpControllerSelector
chooses the controller type from this list.
IAssembliesResolver Gets the list of project assemblies. The IHttpControllerTypeResolver
interface uses this list to find the controller types.
IHttpControllerActivator Creates new controller instances.
IHttpActionSelector Selects the action.
IHttpActionInvoker Invokes the action.
To provide your own implementation for any of these interfaces, use the Services collection on
the HttpConfiguration object:

var config = GlobalConfiguration.Configuration;


config.Services.Replace(typeof(IHttpControllerSelector), new MyControllerSelector(config));
-------------------

Attribute Routing in ASP.NET Web API 2


By Mike Wasson|January 20, 2014
1292 of 1425 people found this helpful
Print
Routing is how Web API matches a URI to an action. Web API 2 supports a new type of routing,
called attribute routing. As the name implies, attribute routing uses attributes to define routes.
Attribute routing gives you more control over the URIs in your web API. For example, you can
easily create URIs that describe hierarchies of resources.

The earlier style of routing, called convention-based routing, is still fully supported. In fact, you
can combine both techniques in the same project.

This topic shows how to enable attribute routing and describes the various options for attribute
routing. For an end-to-end tutorial that uses attribute routing, see Create a REST API with
Attribute Routing in Web API 2.

Why Attribute Routing?


Enabling Attribute Routing
Adding Route Attributes
Route Prefixes
Route Constraints
Optional URI Parameters and Default Values
Route Names
Route Order
Prerequisites

Visual Studio 2013 or Visual Studio Express 2013

Alternatively, use NuGet Package Manager to install the necessary packages. From the Tools
menu in Visual Studio, select Library Package Manager, then select Package Manager
Console. Enter the following command in the Package Manager Console window:

Install-Package Microsoft.AspNet.WebApi.WebHost

Why Attribute Routing?

The first release of Web API used convention-based routing. In that type of routing, you define
one or more route templates, which are basically parameterized strings. When the framework
receives a request, it matches the URI against the route template. (For more information about
convention-based routing, see Routing in ASP.NET Web API.

One advantage of convention-based routing is that templates are defined in a single place, and
the routing rules are applied consistently across all controllers. Unfortunately, convention-based
routing makes it hard to support certain URI patterns that are common in RESTful APIs. For
example, resources often contain child resources: Customers have orders, movies have actors,
books have authors, and so forth. It’s natural to create URIs that reflect these relations:

/customers/1/orders

This type of URI is difficult to create using convention-based routing. Although it can be done,
the results don’t scale well if you have many controllers or resource types.

With attribute routing, it’s trivial to define a route for this URI. You simply add an attribute to the
controller action:

[Route("customers/{customerId}/orders")]
public IEnumerable<Order> GetOrdersByCustomer(int customerId) { ... }
Here are some other patterns that attribute routing makes easy.

API versioning

In this example, “/api/v1/products” would be routed to a different controller than


“/api/v2/products”.

/api/v1/products
/api/v2/products

Overloaded URI segments

In this example, “1” is an order number, but “pending” maps to a collection.

/orders/1
/orders/pending

Mulitple parameter types

In this example, “1” is an order number, but “2013/06/16” specifies a date.

/orders/1
/orders/2013/06/16

Enabling Attribute Routing

To enable attribute routing, call MapHttpAttributeRoutes during configuration. This extension


method is defined in the System.Web.Http.HttpConfigurationExtensions class.

using System.Web.Http;

namespace WebApplication
{
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API routes
config.MapHttpAttributeRoutes();

// Other Web API configuration not shown.


}
}
}
Attribute routing can be combined with convention-based routing. To define convention-based
routes, call the MapHttpRoute method.

public static class WebApiConfig


{
public static void Register(HttpConfiguration config)
{
// Attribute routing.
config.MapHttpAttributeRoutes();

// Convention-based routing.
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
For more information about configuring Web API, see Configuring ASP.NET Web API 2 .

Note: Migrating From Web API 1

Prior to Web API 2, the Web API project templates generated code like this:

protected void Application_Start()


{
// WARNING - Not compatible with attribute routing.
WebApiConfig.Register(GlobalConfiguration.Configuration);
}
If attribute routing is enabled, this code will throw an exception. If you upgrade an existing Web
API project to use attribute routing, make sure to update this configuration code to the following:

protected void Application_Start()


{
// Pass a delegate to the Configure method.
GlobalConfiguration.Configure(WebApiConfig.Register);
}
For more information, see Configuring Web API with ASP.NET Hosting.

Adding Route Attributes

Here is an example of a route defined using an attribute:

public class OrdersController : ApiController


{
[Route("customers/{customerId}/orders")]
[HttpGet]
public IEnumerable<Order> FindOrdersByCustomer(int customerId) { ... }
}
The string "customers/{customerId}/orders" is the URI template for the route. Web API tries to
match the request URI to the template. In this example, "customers" and "orders" are literal
segments, and "{customerId}" is a variable parameter. The following URIs would match this
template:

http://localhost/customers/1/orders
http://localhost/customers/bob/orders
http://localhost/customers/1234-5678/orders
You can restrict the matching by using constraints, described later in this topic.

Notice that the "{customerId}" parameter in the route template matches the name of the
customerId parameter in the method. When Web API invokes the controller action, it tries to
bind the route parameters. For example, if the URI is http://example.com/customers/1/orders,
Web API tries to bind the value "1" to the customerId parameter in the action.

A URI template can have several parameters:

[Route("customers/{customerId}/orders/{orderId}")]
public Order GetOrderByCustomer(int customerId, int orderId) { ... }
Any controller methods that do not have a route attribute use convention-based routing. That
way, you can combine both types of routing in the same project.

HTTP Methods

Web API also selects actions based on the HTTP method of the request (GET, POST, etc). By
default, Web API looks for a case-insensitive match with the start of the controller method name.
For example, a controller method named PutCustomers matches an HTTP PUT request.

You can override this convention by decorating the mathod with any the following attributes:

[HttpDelete]
[HttpGet]
[HttpHead]
[HttpOptions]
[HttpPatch]
[HttpPost]
[HttpPut]
The following example maps the CreateBook method to HTTP POST requests.

[Route("api/books")]
[HttpPost]
public HttpResponseMessage CreateBook(Book book) { ... }
For all other HTTP methods, including non-standard methods, use the AcceptVerbs attribute,
which takes a list of HTTP methods.

// WebDAV method
[Route("api/books")]
[AcceptVerbs("MKCOL")]
public void MakeCollection() { }
Route Prefixes

Often, the routes in a controller all start with the same prefix. For example:

public class BooksController : ApiController


{
[Route("api/books")]
public IEnumerable<Book> GetBooks() { ... }

[Route("api/books/{id:int}")]
public Book GetBook(int id) { ... }

[Route("api/books")]
[HttpPost]
public HttpResponseMessage CreateBook(Book book) { ... }
}
You can set a common prefix for an entire controller by using the [RoutePrefix] attribute:

[RoutePrefix("api/books")]
public class BooksController : ApiController
{
// GET api/books
[Route("")]
public IEnumerable<Book> Get() { ... }

// GET api/books/5
[Route("{id:int}")]
public Book Get(int id) { ... }

// POST api/books
[Route("")]
public HttpResponseMessage Post(Book book) { ... }
}
Use a tilde (~) on the method attribute to override the route prefix:

[RoutePrefix("api/books")]
public class BooksController : ApiController
{
// GET /api/authors/1/books
[Route("~/api/authors/{authorId:int}/books")]
public IEnumerable<Book> GetByAuthor(int authorId) { ... }

// ...
}
The route prefix can include parameters:

[RoutePrefix("customers/{customerId}")]
public class OrdersController : ApiController
{
// GET customers/1/orders
[Route("orders")]
public IEnumerable<Order> Get(int customerId) { ... }
}

Route Constraints

Route constraints let you restrict how the parameters in the route template are matched. The
general syntax is "{parameter:constraint}". For example:

[Route("users/{id:int}"]
public User GetUserById(int id) { ... }

[Route("users/{name}"]
public User GetUserByName(string name) { ... }
Here, the first route will only be selected if the "id" segment of the URI is an integer. Otherwise,
the second route will be chosen.

The following table lists the constraints that are supported.

Constraint Description Example


alpha Matches uppercase or lowercase Latin alphabet characters (a-z, A-Z) {x:alpha}
bool Matches a Boolean value. {x:bool}
datetime Matches a DateTime value. {x:datetime}
decimal Matches a decimal value. {x:decimal}
double Matches a 64-bit floating-point value.{x:double}
float Matches a 32-bit floating-point value.{x:float}
guid Matches a GUID value. {x:guid}
int Matches a 32-bit integer value. {x:int}
length Matches a string with the specified length or within a specified range of lengths.
{x:length(6)}
{x:length(1,20)}
long Matches a 64-bit integer value. {x:long}
max Matches an integer with a maximum value. {x:max(10)}
maxlength Matches a string with a maximum length. {x:maxlength(10)}
min Matches an integer with a minimum value. {x:min(10)}
minlength Matches a string with a minimum length. {x:minlength(10)}
range Matches an integer within a range of values.{x:range(10,50)}
regex Matches a regular expression. {x:regex(^\d{3}-\d{3}-\d{4}$)}
Notice that some of the constraints, such as "min", take arguments in parentheses. You can
apply multiple constraints to a parameter, separated by a colon.

[Route("users/{id:int:min(1)}")]
public User GetUserById(int id) { ... }

Custom Route Constraints

You can create custom route constraints by implementing the IHttpRouteConstraint interface.
For example, the following constraint restricts a parameter to a non-zero integer value.

public class NonZeroConstraint : IHttpRouteConstraint


{
public bool Match(HttpRequestMessage request, IHttpRoute route, string parameterName,
IDictionary<string, object> values, HttpRouteDirection routeDirection)
{
object value;
if (values.TryGetValue(parameterName, out value) && value != null)
{
long longValue;
if (value is long)
{
longValue = (long)value;
return longValue != 0;
}

string valueString = Convert.ToString(value, CultureInfo.InvariantCulture);


if (Int64.TryParse(valueString, NumberStyles.Integer,
CultureInfo.InvariantCulture, out longValue))
{
return longValue != 0;
}
}
return false;
}
}
The following code shows how to register the constraint:

public static class WebApiConfig


{
public static void Register(HttpConfiguration config)
{
var constraintResolver = new DefaultInlineConstraintResolver();
constraintResolver.ConstraintMap.Add("nonzero", typeof(NonZeroConstraint));

config.MapHttpAttributeRoutes(constraintResolver);
}
}
Now you can apply the constraint in your routes:

[Route("{id:nonzero}")]
public HttpResponseMessage GetNonZero(int id) { ... }
You can also replace the entire DefaultInlineConstraintResolver class by implementing the
IInlineConstraintResolver interface. Doing so will replace all of the built-in constraints, unless
your implementation of IInlineConstraintResolver specifically adds them.

Optional URI Parameters and Default Values

You can make a URI parameter optional by adding a question mark to the route parameter. If a
route parameter is optional, you must define a default value for the method parameter.

public class BooksController : ApiController


{
[Route("api/books/locale/{lcid:int?}")]
public IEnumerable<Book> GetBooksByLocale(int lcid = 1033) { ... }
}
In this example, /api/books/locale/1033 and /api/books/locale return the same resource.

Alternatively, you can specify a default value inside the route template, as follows:

public class BooksController : ApiController


{
[Route("api/books/locale/{lcid:int=1033}")]
public IEnumerable<Book> GetBooksByLocale(int lcid) { ... }
}
This is almost the same as the previous example, but there is a slight difference of behavior
when the default value is applied.

In the first example ("{lcid?}"), the default value of 1033 is assigned directly to the method
parameter, so the parameter will have this exact value.
In the second example ("{lcid=1033}"), the default value of "1033" goes through the
model-binding process. The default model-binder will convert "1033" to the numeric value 1033.
However, you could plug in a custom model binder, which might do something different.
(In most cases, unless you have custom model binders in your pipeline, the two forms will be
equivalent.)

Route Names

In Web API, every route has a name. Route names are useful for generating links, so that you
can include a link in an HTTP response.

To specify the route name, set the Name property on the attribute. The following example
shows how to set the route name, and also how to use the route name when generating a link.

public class BooksController : ApiController


{
[Route("api/books/{id}", Name="GetBookById")]
public BookDto GetBook(int id)
{
// Implementation not shown...
}

[Route("api/books")]
public HttpResponseMessage Post(Book book)
{
// Validate and add book to database (not shown)

var response = Request.CreateResponse(HttpStatusCode.Created);

// Generate a link to the new book and set the Location header in the response.
string uri = Url.Link("GetBookById", new { id = book.BookId });
response.Headers.Location = new Uri(uri);
return response;
}
}

Route Order

When the framework tries to match a URI with a route, it evaluates the routes in a particular
order. To specify the order, set the RouteOrder property on the route attribute. Lower values are
evaluated first. The default order value is zero.

Here is how the total ordering is determined:

Compare the RouteOrder property of the route attribute.


Look at each URI segment in the route template. For each segment, order as follows:
Literal segments.
Route parameters with constraints.
Route parameters without constraints.
Wildcard parameter segments with constraints.
Wildcard parameter segments without constraints.
In the case of a tie, routes are ordered by a case-insensitive ordinal string comparison
(OrdinalIgnoreCase) of the route template.
Here is an example. Suppose you define the following controller:

[RoutePrefix("orders")]
public class OrdersController : ApiController
{
[Route("{id:int}")] // constrained parameter
public HttpResponseMessage Get(int id) { ... }

[Route("details")] // literal
public HttpResponseMessage GetDetails() { ... }

[Route("pending", RouteOrder = 1)]


public HttpResponseMessage GetPending() { ... }

[Route("{customerName}")] // unconstrained parameter


public HttpResponseMessage GetByCustomer(string customerName) { ... }

[Route("{*date:datetime}")] // wildcard
public HttpResponseMessage Get(DateTime date) { ... }
}
These routes are ordered as follows.
orders/details
orders/{id}
orders/{customerName}
orders/{*date}
orders/pending
Notice that "details" is a literal segment and appears before "{id}", but "pending" appears last
because the RouteOrder property is 1. (This example assumes there are no customers named
"details" or "pending". In general, try to avoid ambiguous routes. In this example, a better route
template for GetByCustomer is "customers/{customerName}" )
------------------------

Create a REST API with Attribute Routing in ASP.NET Web API 2


By Mike Wasson|June 26, 2013
568 of 625 people found this helpful
Print
Web API 2 supports a new type of routing, called attribute routing. For a general overview of
attribute routing, see Attribute Routing in Web API 2. In this tutorial, you will use attribute routing
to create a REST API for a collection of books. The API will support the following actions:

Action Example URI


Get a list of all books. /api/books
Get a book by ID. /api/books/1
Get the details of a book. /api/books/1/details
Get a list of books by genre. /api/books/fantasy
Get a list of books by publication date. /api/books/date/2013-02-16
/api/books/date/2013/02/16 (alternate form)
Get a list of books by a particular author. /api/authors/1/books
All methods are read-only (HTTP GET requests).

For the data layer, we'll use Entity Framework. Book records will have the following fields:

ID
Title
Genre
Publication date
Price
Description
AuthorID (foreign key to an Authors table)
For most requests, however, the API will return a subset of this data (title, author, and genre).
To get the complete record, the client requests /api/books/{id}/details.

Prerequisites
Visual Studio 2013 or Visual Studio Express 2013

Create the Visual Studio Project

Start by running Visual Studio. From the File menu, select New and then select Project.

In the Templates pane, select Installed Templates and expand the Visual C# node. Under
Visual C#, select Web. In the list of project templates, select ASP.NET MVC 4 Web Application.
Name the project "BooksAPI".

In the New ASP.NET Project dialog, select the Empty template. Under “Add folders and core
references for”, select the Web API checkbox. Click Create Project.

This creates a skeleton project that is configured for Web API functionality.

Domain Models

Next, add classes for domain models. In Solution Explorer, right-click the Models folder. Select
Add, then select Class. Name the class Author.

Replace the code in Author.cs with the following:

using System.ComponentModel.DataAnnotations;

namespace BooksAPI.Models
{
public class Author
{
public int AuthorId { get; set; }
[Required]
public string Name { get; set; }
}
}
Now add another class named Book.

using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace BooksAPI.Models
{
public class Book
{
public int BookId { get; set; }
[Required]
public string Title { get; set; }
public decimal Price { get; set; }
public string Genre { get; set; }
public DateTime PublishDate { get; set; }
public string Description { get; set; }
public int AuthorId { get; set; }
[ForeignKey("AuthorId")]
public Author Author { get; set; }
}
}

Add a Web API Controller

In this step, we'll add a Web API controller that uses Entity Framework as the data layer.

Press CTRL+SHIFT+B to build the project. Entity Framework uses reflection to discover the
properties of the models, so it requires a compiled assembly to create the database schema.

In Solution Explorer, right-click the Controllers folder. Select Add, then select Controller.

In the Add Scaffold dialog, select “Web API 2 Controller with read/write actions, using Entity
Framework.”

In the Add Controller dialog, for Controller name, enter "BooksController". Select the "Use async
controller actions" checkbox. For Model class, select "Book". (If you don’t see the Book class
listed in the dropdown, make sure that you built the project.) Then click the “<New data
context...>” button.

Click Add in the New Data Context dialog.


Click Add in the Add Controller dialog. The scaffolding adds a class named BooksController that
defines the API controller. It also adds a class named BooksAPIContext in the Models folder,
which defines the data context for Entity Framework.

Seed the Database

From the Tools menu, select Library Package Manager, and then select Package Manager
Console.

In the Package Manager Console window, enter the following command:

enable-migrations
This command creates a Migrations folder and adds a new code file named Configuration.cs.
Open this file and add the following code to the Configuration.Seed method.

protected override void Seed(BooksAPI.Models.BooksAPIContext context)


{
context.Authors.AddOrUpdate(new Author[] {
new Author() { AuthorId = 1, Name = "Ralls, Kim" },
new Author() { AuthorId = 2, Name = "Corets, Eva" },
new Author() { AuthorId = 3, Name = "Randall, Cynthia" },
new Author() { AuthorId = 4, Name = "Thurman, Paula" }
});

context.Books.AddOrUpdate(new Book[] {
new Book() { BookId = 1, Title= "Midnight Rain", Genre = "Fantasy",
PublishDate = new DateTime(2000, 12, 16), AuthorId = 1, Description =
"A former architect battles an evil sorceress.", Price = 14.95M },

new Book() { BookId = 2, Title = "Maeve Ascendant", Genre = "Fantasy",


PublishDate = new DateTime(2000, 11, 17), AuthorId = 2, Description =
"After the collapse of a nanotechnology society, the young" +
"survivors lay the foundation for a new society.", Price = 12.95M },

new Book() { BookId = 3, Title = "The Sundered Grail", Genre = "Fantasy",


PublishDate = new DateTime(2001, 09, 10), AuthorId = 2, Description =
"The two daughters of Maeve battle for control of England.", Price = 12.95M },
new Book() { BookId = 4, Title = "Lover Birds", Genre = "Romance",
PublishDate = new DateTime(2000, 09, 02), AuthorId = 3, Description =
"When Carla meets Paul at an ornithology conference, tempers fly.", Price = 7.99M },

new Book() { BookId = 5, Title = "Splish Splash", Genre = "Romance",


PublishDate = new DateTime(2000, 11, 02), AuthorId = 4, Description =
"A deep sea diver finds true love 20,000 leagues beneath the sea.", Price = 6.99M},
});
}
In the Package Manager Console window, type the following commands.

add-migration Initial

update-database
These commands create a local database and invoke the Seed method to populate the
database.

Add DTO Classes

If you run the application now and send a GET request to /api/books/1, the response looks
similar to the following. (I added indentation for readability.)

{
"BookId": 1,
"Title": "Midnight Rain",
"Genre": "Fantasy",
"PublishDate": "2000-12-16T00:00:00",
"Description": "A former architect battles an evil sorceress.",
"Price": 14.95,
"AuthorId": 1,
"Author": null
}
Instead, I want this request to return a subset of the fields. Also, I want it to return the author's
name, rather than the author ID. To accomplish this, we'll modify the controller methods to
return a data transfer object (DTO) instead of the EF model. A DTO is an object that is designed
only to carry data.

In Solution Explorer, right-click the project and select Add | New Folder. Name the folder
"DTOs". Add a class named BookDto to the DTOs folder, with the following definition:

namespace BooksAPI.DTOs
{
public class BookDto
{
public string Title { get; set; }
public string Author { get; set; }
public string Genre { get; set; }
}
}
Add another class named BookDetailDto.

using System;

namespace BooksAPI.DTOs
{
public class BookDetailDto
{
public string Title { get; set; }
public string Genre { get; set; }
public DateTime PublishDate { get; set; }
public string Description { get; set; }
public decimal Price { get; set; }
public string Author { get; set; }
}
}
Next, update the BooksController class to return BookDto instances. We'll use the
Queryable.Select method to project Book instances to BookDto instances. Here is the updated
code for the controller class.

using BooksAPI.DTOs;
using BooksAPI.Models;
using System;
using System.Data.Entity;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;
using System.Web.Http;
using System.Web.Http.Description;

namespace BooksAPI.Controllers
{
public class BooksController : ApiController
{
private BooksAPIContext db = new BooksAPIContext();
// Typed lambda expression for Select() method.
private static readonly Expression<Func<Book, BookDto>> AsBookDto =
x => new BookDto
{
Title = x.Title,
Author = x.Author.Name,
Genre = x.Genre
};

// GET api/Books
public IQueryable<BookDto> GetBooks()
{
return db.Books.Include(b => b.Author).Select(AsBookDto);
}

// GET api/Books/5
[ResponseType(typeof(BookDto))]
public async Task<IHttpActionResult> GetBook(int id)
{
BookDto book = await db.Books.Include(b => b.Author)
.Where(b => b.BookId == id)
.Select(AsBookDto)
.FirstOrDefaultAsync();
if (book == null)
{
return NotFound();
}

return Ok(book);
}

protected override void Dispose(bool disposing)


{
db.Dispose();
base.Dispose(disposing);
}
}
}
I deleted the PutBook, PostBook, and DeleteBook methods, because they aren't needed for this
tutorial.

Now if you run the application and request /api/books/1, the response body should look like this:
{"Title":"Midnight Rain","Author":"Ralls, Kim","Genre":"Fantasy"}
Add Route Attributes

Next, we'll convert the controller to use attribute routing. First, add a RoutePrefix attribute to the
controller. This attribute defines the initial URI segments for all methods on this controller.

[RoutePrefix("api/books")]
public class BooksController : ApiController
{
// ...
Then add [Route] attributes to the controller actions, as follows:

[Route("")]
public IQueryable<BookDto> GetBooks()
{
// ...
}

[Route("{id:int}")]
[ResponseType(typeof(BookDto))]
public async Task<IHttpActionResult> GetBook(int id)
{
// ...
}
The route template for each controller method is the prefix plus the string specified in the Route
attribute. For the GetBook method, the route template includes the parameterized string
"{id:int}", which matches if the URI segment contains an integet value.

Method Route Template Example URI


GetBooks "api/books" http://localhost/api/books
GetBook "api/books/{id:int}" http://localhost/api/books/5
Get Book Details

To get book details, the client will send a GET request to /api/books/{id}/details, where {id} is the
ID of the book.

Add the following method to the BooksController class.

[Route("{id:int}/details")]
[ResponseType(typeof(BookDetailDto))]
public async Task<IHttpActionResult> GetBookDetail(int id)
{
var book = await (from b in db.Books.Include(b => b.Author)
where b.AuthorId == id
select new BookDetailDto
{
Title = b.Title,
Genre = b.Genre,
PublishDate = b.PublishDate,
Price = b.Price,
Description = b.Description,
Author = b.Author.Name
}).FirstOrDefaultAsync();

if (book == null)
{
return NotFound();
}
return Ok(book);
}
If you request /api/books/1/detail, the response looks like this:

{
"Title": "Midnight Rain",
"Genre": "Fantasy",
"PublishDate": "2000-12-16T00:00:00",
"Description": "A former architect battles an evil sorceress.",
"Price": 14.95,
"Author": "Ralls, Kim"
}
Get Books By Genre

To get a list of books in a specific genre, the client will send a GET request to /api/books/genre,
where genre is the name of the genre. (For example, /get/books/fantasy.)

Add the following method to BooksController.

[Route("{genre}")]
public IQueryable<BookDto> GetBooksByGenre(string genre)
{
return db.Books.Include(b => b.Author)
.Where(b => b.Genre.Equals(genre, StringComparison.OrdinalIgnoreCase))
.Select(AsBookDto);
}
Here we are defining a route that contains a {genre} parameter in the URI template. Notice that
Web API is able to distinguish these two URIs and route them to different methods:

/api/books/1

/api/books/fantasy

That's because the GetBook method includes a constraint that the "id" segment must be an
integer value:

[Route("{id:int}")]
public BookDto GetBook(int id)
{
// ...
}
If you request /api/books/fantasy, the response looks like this:

[ { "Title": "Midnight Rain", "Author": "Ralls, Kim", "Genre": "Fantasy" }, { "Title": "Maeve
Ascendant", "Author": "Corets, Eva", "Genre": "Fantasy" }, { "Title": "The Sundered Grail",
"Author": "Corets, Eva", "Genre": "Fantasy" } ]

Get Books By Author

To get a list of a books for a particular author, the client will send a GET request to
/api/authors/id/books, where id is the ID of the author.

Add the following method to BooksController.

[Route("~api/authors/{authorId}/books")]
public IQueryable<BookDto> GetBooksByAuthor(int authorId)
{
return db.Books.Include(b => b.Author)
.Where(b => b.AuthorId == authorId)
.Select(AsBookDto);
}
This example is interesting because "books" is treated a child resource of "authors". This pattern
is quite common in RESTful APIs.

The tilde (~) in the route template overrides the route prefix in the RoutePrefix attribute.

Get Books By Publication Date


To get a list of books by publication date, the client will send a GET request to
/api/books/date/yyyy-mm-dd, where yyyy-mm-dd is the date.

Here is one way to do this:

[Route("date/{pubdate:datetime}")]
public IQueryable<BookDto> GetBooks(DateTime pubdate)
{
return db.Books.Include(b => b.Author)
.Where(b => DbFunctions.TruncateTime(b.PublishDate)
== DbFunctions.TruncateTime(pubdate))
.Select(AsBookDto);
}
The {pubdate:datetime} parameter is constrained to match a DateTime value. This works, but
it's actually more permissive than we'd like. For example, these URIs will also match the route:

/api/books/date/Thu, 01 May 2008

/api/books/date/2000-12-16T00:00:00

There's nothing wrong with allowing these URIs. However, you can restrict the route to a
particular format by adding a regular-expression constraint to the route template:

[Route("api/books/date/{pubdate:datetime:regex(\\d{4}-\\d{2}-\\d{2})}")]
public IQueryable<BookDto> GetBooks(DateTime pubdate)
{
// ...
}
Now only dates in the form "yyyy-mm-dd" will match. Notice that we don't use the regex to
validate that we got a real date. That is handled when Web API tries to convert the URI segment
into a DateTime instance. An invalid date such as '2012-47-99' will fail to be converted, and the
client will get a 404 error.

You can also support a slash separator (/api/books/date/yyyy/mm/dd) by adding another [Route]
attribute with a different regex.

[Route("date/{pubdate:datetime:regex(\\d{4}-\\d{2}-\\d{2})}")]
[Route("date/{*pubdate:datetime:regex(\\d{4}/\\d{2}/\\d{2})}")] // new
public IQueryable<BookDto> GetBooks(DateTime pubdate)
{
// ...
}
There is a subtle but important detail here. The second route template has a wildcard character
(*) at the start of the {pubdate} parameter:

{*pubdate: ... }
This tells the routing engine that {pubdate} should match the rest of the URI. By default, a
template parameter matches a single URI segment. In this case, we want {pubdate} to span
several URI segments:

/api/books/date/2013/06/17

Controller Code

Here is the complete code for the BooksController class.

using BooksAPI.DTOs;
using BooksAPI.Models;
using System;
using System.Data.Entity;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;
using System.Web.Http;
using System.Web.Http.Description;

namespace BooksAPI.Controllers
{
[RoutePrefix("api/books")]
public class BooksController : ApiController
{
private BooksAPIContext db = new BooksAPIContext();

// Typed lambda expression for Select() method.


private static readonly Expression<Func<Book, BookDto>> AsBookDto =
x => new BookDto
{
Title = x.Title,
Author = x.Author.Name,
Genre = x.Genre
};

// GET api/Books
[Route("")]
public IQueryable<BookDto> GetBooks()
{
return db.Books.Include(b => b.Author).Select(AsBookDto);
}

// GET api/Books/5
[Route("{id:int}")]
[ResponseType(typeof(BookDto))]
public async Task<IHttpActionResult> GetBook(int id)
{
BookDto book = await db.Books.Include(b => b.Author)
.Where(b => b.BookId == id)
.Select(AsBookDto)
.FirstOrDefaultAsync();
if (book == null)
{
return NotFound();
}

return Ok(book);
}

[Route("{id:int}/details")]
[ResponseType(typeof(BookDetailDto))]
public async Task<IHttpActionResult> GetBookDetail(int id)
{
var book = await (from b in db.Books.Include(b => b.Author)
where b.AuthorId == id
select new BookDetailDto
{
Title = b.Title,
Genre = b.Genre,
PublishDate = b.PublishDate,
Price = b.Price,
Description = b.Description,
Author = b.Author.Name
}).FirstOrDefaultAsync();

if (book == null)
{
return NotFound();
}
return Ok(book);
}
[Route("{genre}")]
public IQueryable<BookDto> GetBooksByGenre(string genre)
{
return db.Books.Include(b => b.Author)
.Where(b => b.Genre.Equals(genre, StringComparison.OrdinalIgnoreCase))
.Select(AsBookDto);
}

[Route("~api/authors/{authorId}/books")]
public IQueryable<BookDto> GetBooksByAuthor(int authorId)
{
return db.Books.Include(b => b.Author)
.Where(b => b.AuthorId == authorId)
.Select(AsBookDto);
}

[Route("date/{pubdate:datetime:regex(\\d{4}-\\d{2}-\\d{2})}")]
[Route("date/{*pubdate:datetime:regex(\\d{4}/\\d{2}/\\d{2})}")]
public IQueryable<BookDto> GetBooks(DateTime pubdate)
{
return db.Books.Include(b => b.Author)
.Where(b => DbFunctions.TruncateTime(b.PublishDate)
== DbFunctions.TruncateTime(pubdate))
.Select(AsBookDto);
}

protected override void Dispose(bool disposing)


{
db.Dispose();
base.Dispose(disposing);
}
}
}
--------------------------
Routing Basics in ASP.NET Web API

John Atten, 22 Aug 2013 CPOL

4.82 (18 votes)


Rate this:
vote 1vote 2vote 3vote 4vote 5
This post covers the most basic and fundamental concepts of routing as applied to the
ASP.NET Web API framework.
I210-and-I57-interchange-by-Rob-Reiring-320

As noted in Routing Basics in ASP.NET MVC, routing in ASP.NET Web API is functionally very
similar to the standard MVC routing. Understanding the MVC routing model will provide most of
what you need to know to leverage that knowledge against the Web API framework, so long as
you keep in mind the key differences between the two.

The differences between the two are largely dictated by the different consumption models
driving each type of application.

Image by Ron Reiring

Important note: This post covers the most basic and fundamental concepts of routing as applied
to the ASP.NET Web API framework. The target audience are those with little or no familiarity
with routing in general, or who may be looking to understand the most basic differences
between routing in ASP.NET MVC and Web API.

If you have little to no knowledge of MVC routing, you may want to review my post on MVC
routing basics first.

In my next post, having covered the fundamentals, I will examine route customization.

Web API Configuration Files


How Routing Works for Web API
The Default Web API Route Template
Action Method Selection
Web API and Action Naming
What Have We Learned?
Other Posts You May Find Useful
Web API and MVC – Two Separate Frameworks

Because the Web API grew (in part) out of the efforts of the ASP.NET MVC team, and because
the default Web API project template in Visual Studio is bundled up inside an MVC application,
it is easy to think that the Web API framework is some kind of subset of the MVC framework. In
fact, the two inter-operate together very well, but that is by design. They are, in fact, separate
frameworks which adhere to some common architectural patterns.

Instead of paraphrasing the overview of Web API and the architectural goals of the project, I will
let the MVC team do so, because honestly, they know better than I do! from the most helpful
book Professional ASP.NET MVC 4 authored by (mostly) the MVC team:
"ASP.NET MVC excels at accepting form data and generating HTML; ASP.NET Web API excels
at accepting and generating structured data like JSON and XML." MVC has flirted with providing
structured data support (with JsonResult and the JSON value provider), but it still fell short in
several ways that are important to API programmers, including:

Dispatching to actions based on HTTP verbs rather than action names


Accepting and generating content which may not necessarily be object oriented (not only XML,
but also content like images, PDF files, or VCARDs
Content type negotiation, which allows the developer to both accept and genereate structured
content independent of its wire representation
Hosting outside of the ASP.NET runtime stack and IIS web server, something which WCF has
been unable to do for years
The Web API team went to great lengths to try to allow you to leverage your existing ASP.NET
experience with controllers, actions, filters, model binders, dependency injection, and the like.
Many of these same concepts appear in Web API in very similar forms, which make applications
that combine MVC and Web API seem very well integrated."

As noted above, one of the key differences between MVC and Web API is that Web API returns
an appropriate representation of the model object as a result. A related difference is that Web
API performs content type negotiation in response to incoming requests, and attempts to return
the proper content type (JSON in response to an incoming request specifying JSON as the
preferred content resource representation, for example).

Suffice it to say that Web API is an effort to create a mechanism for the efficient exchange of
data and other content using HTTP. This effort is reflected in the architecture of the framework,
and results in some of the differences in routing between the two frameworks.

Web API Route Configuration Files

The default Visual Studio Web API project template is rather large, as it incorporates a complete
MVC project as well. The resulting project has some pretty cool features, including automatic
documentation for the API you build (that is the purpose of the MVC site contained in the
project), but also presents a rather bloated project file, with a large number of folders and
dependencies.

NOTE: To see how to create a stripped-down Web API project template in Visual Studio, see
Creating a Clean, Minimal-Footprint ASP.NET WebAPI Project with VS 2012 and ASP.NET
MVC 4

As with a standard MVC project, the route configuration is called from the Global.asx file.
However, in this standard Web API project, there exists both a RouteConfig class, and a
WebApiConfig class, both in the Application_Start folder:
Global.asx File and the WebApiConfig File in a Typical MVC Project:
StandardWebApiTemplateProject

The RouteConfig.cs file here is the same as in any MVC project, and sets up routes for the MVC
framework. The WebApiConfig.cs file is where our Web API routing configuration happens.
However, if we open the file, it looks pretty familiar:

The WebApiConfig Class and MapHttpRoute Method:


Hide Copy Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;

namespace StandardWebApiTemplateProject
{
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
}
There are a few important differences here, though. First, notice that in the using statements at
the top of the file, there are no references toSystem.Web.Mvc but instead, we find a reference
to System.Web.Http. That's because the Web API team re-created the routing functionality in a
library with no dependencies on ASP.NET or MVC. Also notice that instead of calling
Routes.MapRoutes as in the MVC RouteConfig class, we instead call
Config.Routes.MapHttpRoutes.

And, as we can see, the default route template for Web API looks a little different.

How Routing Works for Web API

Unlike ASP.NET MVC, the Web API routing convention routes incoming requests to a specific
controller, but by default simply matches the HTTP verb of the request to an action method
whose name begins with that verb. Recall the default MVC route configuration:
The Default MVC Route Template:
Hide Copy Code
{controller}/{action}/{id}
In contrast, the default Web API route template looks like this:

The Default Web API Route Template:


Hide Copy Code
api/{controller}/{id}
The literal api at the beginning of the Web API route template above makes it distinct from the
standard MVC route. Also, it is a good convention to include as part of an API route a segment
that lets the consumer know they are accessing an API instead of a standard site.

Also notice that unlike the familiar MVC route template, the Web API template does not specify
an {action} route parameter. This is because, as we mentioned earlier, the Web API framework
will by default map incoming requests to the appropriate action based upon the HTTP verb of
the request.

Consider the following typical Web API Controller:

WebApi Controller from Default Visual Studio WebApi Template


Hide Shrink Copy Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;

namespace StandardWebApiTemplateProject.Controllers
{
public class ValuesController : ApiController
{
// GET api/values
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}

// GET api/values/5
public string Get(int id)
{
return "value";
}

// POST api/values
public void Post([FromBody]string value)
{
}

// PUT api/values/5
public void Put(int id, [FromBody]string value)
{
}

// DELETE api/values/5
public void Delete(int id)
{
}
}
}
First, take note that Web API controllers do not inherit from System.Web.Mvc.Controller, but
instead from System.Web.Http.Controller. Again, we are working with a familiar, but distinct
library.

Of particular note, however, are the default method names (the example above is what is
created as part of the default VS 2012 project template). Again, without specifying a specific
method using an {action} route parameter, the Web API framework determines the appropriate
route based on the HTTP verb of the incoming request, and calls the proper method
accordingly.

The following incoming URL, included as part of an HTTP GET message, would map to the first
Get() method as defined in the controller above:

Example URL With No ID Parameter


Hide Copy Code
http://mydomain/values/
Similarly, this URL, also as part of an HTTP GET request, would map to the second Get(id)
method:

Example URL Including ID Parameter


Hide Copy Code
http://mydomain/values/5
We could, however, modify our controller thusly, and the routing would still work without
modification:
Modifications to the ValuesController Class:
Hide Copy Code
// GET api/values
public IEnumerable<string> GetValues()
{
return new string[] { "value1", "value2" };
}

// GET api/values/5
public string GetValue(int id)
{
return "value";
}

// POST api/values
public void PostValue([FromBody]Book value)
{
}

// PUT api/values/5
public void PutValue(int id, [FromBody]string value)
{
}

// DELETE api/values/5
public void DeleteValue(int id)
{
Note that we retained the HTTP action verb as a prefix to all of our method names. Under these
circumstances, the unmodified route parameter will still work just fine. When per convention, no
{action} route parameter is specified, the Web API framework again appends the "Controller"
suffix to the value provided for the {controller} parameter, and then scans the project for a
suitably named class (in this case, one which derives from ApiController).

Action Method Selection

Once the proper controller class is selected, the framework examines the HTTP action verb of
the request, and searches the class for method names with a matching prefix.

In order to determine the proper method, the framework then examines the additional URL
parameters and attempts to match them with method arguments by name (case insensitive).
The method with the most matching arguments will be selected.
An item to note here. Unlike in MVC, in Web API complex types are not allowed as part of the
URL. Complex types must be placed in the body of the HTTP message. Also, there can be one,
and only one such complex type in the message body.

In evaluating parameter matches against method arguments, any complex types and URL query
strings are disregarded when searching for a match.

Web API and Action Naming

We can modify our default Web API route to include an {action} route parameter, in which case
selection will occur similar to that in MVC. However, action methods defined on our controller
still need to include the proper HTTP action verb prefix, and incoming URLs must use the full
method name.

If we modify our default route thusly, adding an {action} parameter:

The Modified WebApiConfig Class and MapHttpRoute Method:


Hide Copy Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;

namespace StandardWebApiTemplateProject
{
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
}
To see how this works, consider the incoming URL:

Hide Copy Code


http://mydomain/values/5
This will no longer work. If we wish to make a request of our modified ValuesController now, we
would need to submit:
Hide Copy Code
http://mydomain/values/GetValue/5
Review of the Basics for Web API Routing

The routing convention for Web API is to route URLs to a controller, and then to the action
which matches the HTTP verb of the request message. Action methods on the controller must
either match the HTTP action verb, or at least include the action verb as a prefix for the method
name.
The default route template for a Web API Project is {controller}/{id} where the {id} parameter is
optional.
Web API route templates may optionally include an {action} parameter. However, the action
methods defined on the controller must be named with the proper HTTP action verb as a prefix
in order for the routing to work.
In matching incoming HTTP messages to controllers, the Web API framework identifies the
proper controller by appending the literal "Controller" to the value of the {controller} route
parameter, then scans the project for a class matching that name.
Actions are selected from the controller by considering the non-complex route parameters, and
matching them by name to the arguments of each method which matches the HTTP verb of the
request. The method which matches the most parameters is selected.
Unlike MVC, URLs in Web API cannot contain complex types. Complex types must be placed in
the HTTP message body. There may be one, and only one complex type in the body of an
HTTP message.
That was Pretty Darn Basic. What Next?

The above represents a very simple overview of the Web API routing basics, focusing on the
default configurations and conventions. In the next post we will examine more advanced routing
considerations, and route customization.
---------------------
Exploring routing in Web API
MORE LIKE THIS
mvc 6
New features in MVC 6
Female executive at laptop with code flying out of screen woman
Top 10 new features in ASP.Net 5
web api performance
Improving Web API performance
on IDG Answers
I am original owner of ipod touch but I let my friend use it and her cousin...

Routing in Web Api


Routing in Web Api
Take advantage of routing in Web API to have more control over the URIs for performing the
HTTP operations

InfoWorld | Jun 30, 2015 Like this article? thumbsup 0 thumbsdown

RELATED TOPICS
Application Development .Net
COMMENTS
ASP.Net Web API is a lightweight framework used for building stateless HTTP services. You
can use Web API to design and implement RESTful services that run on HTTP. REST is an
architectural style -- a set of constraints used to implement stateless services. Web API has
already become the technology of choice for building light weight HTTP services. In this post, I'll
present a discussion on how routing works in Web API.

collage with gears machine data


Review: 6 machine learning clouds
Amazon, Microsoft, Databricks, Google, HPE, and IBM machine learning toolkits run the gamut
in breadth,
READ NOW
When you create a Web API project in Visual Studio, you would observe that a MVC project is
created as well. Similar to ASP.Net MVC the routing configuration in a Web API project is
invoked from the Global.asax file. A Web API project stores the configuration information in the
RouteConfig and WebApiConfig classes -- both of these are present in the Application_Start
folder. Similar to a MVC project you would observe a RouteConfig.cs file created in the
App_Start folder in your solution.

A controller in Web API is responsible for handling HTTP requests. The public methods of the
controller are known as action methods. As soon as a request is received, the Web API runtime
routes the request to the appropriate action to handle the request. Now, in order to determine
which action should be invoked, the Web API runtime takes advantage of a routing table. In
contrast to a typical ASP.Net MVC application, the Web API runtime routes the incoming
requests to the appropriate controller by matching the HTTP verb of the request to the
appropriate action method.

With ASP.Net 5 (to be released soon as part of Visual Studio 2015), there is a unified core
framework -- you have a single outing framework, a single model binding framework, and a
one-filter pipeline. You now have one unified core for ASP.Net MVC, ASP.Net Web API, and
ASP.Net Web Pages. So, there's now only one type of a controller to handle requests: it's
common to your ASP.Net MVC, ASP.Net Web API, and ASP.Net applications.

The default MVC route template looks like this:


{controller}/{action}/{id}
In contrast, the default Web API route looks like this:

api/{controller}/{id}
The default route created when you create a new Web API project in Visual Studio looks like
this:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}

Note how the default route is prefixed by "api". It is a good practice to define the routes of your
Web API application by prefixing them with "api" to make them distinct from the standard MVC
route. On a different note, when you look at the default route for a Web API project, you wouldn't
see the "{action}" route parameter -- the Web API runtime maps requests to the appropriate
actions based on the HTTP verb of the requests.

However, you can modify the Web API route definition to include an "{action}" parameter. The
following code snippet illustrates how the modified WebApiConfig class looks like.

public static class WebApiConfig


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

Now that you have specified "{action}" as part of the route, you need to specify the action when
invoking the WebAPI method. Consider the following URL: http://idgservice/authors/1
In this URL, idgservice is the name of the domain where the WebAPI has been hosted, authors
is the controller name, and 1 is passed as a parameter. However, this wouldn't work if you have
defined "{action}" in your route definition. You would need to explicitly mention the action name
when calling your WebAPI this this case. Here's the correct URL that includes the action name
as part of the URL: http://idgservice/authors/GetAuthorDetails/1

Note that the action name in the above URL is GetAuthorDetails and has been mentioned as
part of the modified URL.

You can also specify the HTTP method for an action using the HttpGet, HttpPut, HttpPost, or
HttpDelete attribute. The code snippet given below illustrates how this can be achieved:

public class AuthorsController : ApiController


{
[HttpGet]
public Author GetAuthor(id) {}
}

If you would like to allow multiple HTTP methods for an action, you can take advantage of the
AcceptVerbs attribute as shown below:

public class ProductsController : ApiController


{
[AcceptVerbs("GET", "HEAD")]
public Author GetAuthor(id) { }
}

RESOURCES

Salesforce App Cloud Solution Center

WHITE PAPER
Industry Report Provides Key Insights for Cloud Migration
SEE ALL
Search Resources
Go
You can also override the action using the ActionName attribute as shown in the code snippet
given below:

public class AuthorsController : ApiController


{
[HttpGet]
[ActionName("AuthorDetails")]
public Author GetAuthor(id) {}
}
Note that you can also prevent a method from being invoked as an action by leveraging the
NonAction attribute as shown below.
public class AuthorsController : ApiController
{
[HttpGet]
[NonAction]
public Boolean ValidateLogin(id) {}
}
---------------------------
Practical Use of ASP.NET Web API Attribute Routing in an MVC application
Posted by: Mahesh Sabnis , on 8/26/2014, in Category ASP.NET MVC
Views: 34488 Tweet Abstract: In ASP.NET Web API 2 a feature called Attribute Routing was
introduced. This article demonstrates uses of the Attribute Routing in an ASP.NET MVC and
Knockout.js application.
ASP.NET MVC is now widely used for web development on the .NET platform. It can be easily
be integrated with the client-side JavaScript Frameworks and Libraries. The framework has
incrementally progressed from one version to the other. In the latest stable release of MVC 5
and WEB API 2 a relatively new feature named ‘Attribute Routing’ was introduced. This feature
provides more control over the URIs in ASP.NET WebAPI for performing HTTP Operations. In
earlier versions of WEB API we had conventional routing and separate action methods for Http
GET,POST, PUT and DELETE which made it challenging to define action methods for similar
Http operations (like multiple Http GET actions). In WEB API 2 with the advantage of the
attribute routing, we can have multiple similar actions in the same API controller class.

Useful .NET and JavaScript Tools to improve your Productivity. Try for Free.

Note: This article shows uses of the Attribute Routing in WEB API 2. You can take an overview
of the other features on WebAPI in What's New in ASP.NET Web API 2.0 .

To understand the context better, check a previous article of mine titled Customizing ASP.NET
Web API Routing for the User Defined methods in ApiController class to understand the
challenges of having similar Http actions in a previous version of WEB API, v1.0.

Practical need of attribute routing in ASP.NET WEB API 2.0

Consider a scenario where you need to retrieve the Sales information of each Sales Agent in
each Territory. In the database, the Sales table has references of AgentId and TerritoryId as
shown here:

webapi-db-relations
The above design clearly specifies that Sales is a logical child of Agent and Territory (and
Product). This means if we need to access Sales data with logical combinations of Agent and
the Territory using HTTP, then the URL can be really complex. For e.g. if we want to retrieve
Sales data based on AgentId for a specific Territory then the expected URL will be as below:

Agent/1/AND/Territory/1 or Agent/1/OR/Territory/1,

In the earlier version, implementing such a complex URL in WEB API (v1.0) actions was difficult.
In WEB API 2, attribute routing can be applied as seen below:

[Route(Agent/1/AND/Territory/1)]

Using WEB API 2 in an ASP.NET MVC Application

In this ASP.NET MVC application, we will be using WEB API 2, EntityFramework, jQuery and
Knockout.js.

Step 1: Open Visual Studio 2013 and create a new Empty ASP.NET MVC Application, name it
as ‘MVC_FIlteringData_WEBAPI’. In the App_Data Folder of the application, add a new SQL
Server Database of the name ‘Company’ and create the following tables:

CREATE TABLE [dbo].[Agent] (


[AgentId] INT IDENTITY (1, 1) NOT NULL,
[AgentName] VARCHAR (50) NOT NULL,
PRIMARY KEY CLUSTERED ([AgentId] ASC)
);

CREATE TABLE [dbo].[Territory] (


[TerritoryId] INT IDENTITY (1, 1) NOT NULL,
[TerritoryName] VARCHAR (50) NOT NULL,
PRIMARY KEY CLUSTERED ([TerritoryId] ASC)
);

CREATE TABLE [dbo].[Product] (


[ProductId] INT IDENTITY (1, 1) NOT NULL,
[ProductName] VARCHAR (50) NOT NULL,
PRIMARY KEY CLUSTERED ([ProductId] ASC)
);

CREATE TABLE [dbo].[Sales] (


[SalesRecordId] INT IDENTITY (1, 1) NOT NULL,
[AgentId] INT NOT NULL,
[TerritoryId] INT NOT NULL,
[ProductId] INT NOT NULL,
[Quantity] INT NOT NULL,
PRIMARY KEY CLUSTERED ([SalesRecordId] ASC),
FOREIGN KEY ([AgentId]) REFERENCES [dbo].[Agent] ([AgentId]),
FOREIGN KEY ([TerritoryId]) REFERENCES [dbo].[Territory] ([TerritoryId]),
FOREIGN KEY ([ProductId]) REFERENCES [dbo].[Product] ([ProductId])
);
Step 2: In the project, in the Models folder, add the ADO.NET EF and select the Company
database created above. After the completion of the wizard of EntityFramework, the mapping
will be displayed as seen here:

webapi-db-relations

Step 3: In the Models folder add a new class:

public class SalesInfo


{
public int SalesRecordId { get; set; }
public string AgentName { get; set; }
public string TerritoryName { get; set; }
public string ProductName { get; set; }
public int Quantity { get; set; }
}
The above class is an arrangement for specifying the format of sales data returned to the client.

Step 4: In the Controllers folder add a new Empty WEB API 2 controller of the name
‘SalesInfoAPIController’. In the controller add the following code:

using MVC_FIlteringData.Models;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;

namespace MVC_FIlteringData.Controllers
{
public class SalesInfoAPIController : ApiController
{
CompanyEntities ctx;
public SalesInfoAPIController()
{
ctx = new CompanyEntities();
}
[Route("Agents")]
public IEnumerable<Agent> GetAgents()
{
List<Agent> Agents = new List<Agent>();

var result = (from a in ctx.Agents


select new {
AgentId = a.AgentId,
AgentName = a.AgentName
}).ToList();

foreach (var item in result)


{
Agents.Add(new Agent() {AgentId = item.AgentId,AgentName = item.AgentName });
}

return Agents;
}

[Route("Territories")]
public IEnumerable<Territory> GetTerritories()
{
List<Territory> Territories = new List<Territory>();

var result = (from a in ctx.Territories


select new
{
TerritoryId = a.TerritoryId,
TerritoryName = a.TerritoryName
}).ToList();

foreach (var item in result)


{
Territories.Add(new Territory() {TerritoryId = item.TerritoryId, TerritoryName =
item.TerritoryName });
}

return Territories;
}
[Route("SalesInfo")]
public IEnumerable<SalesInfo> GetSales()
{
List<SalesInfo> Sales = new List<SalesInfo>();

var result = from s in ctx.Sales


select new {
SalesRecordId = s.SalesRecordId,
AgentId = s.AgentId,
TerritoryId = s.TerritoryId,
ProductId = s.ProductId,
Quantity = s.Quantity
};

foreach (var item in result)


{
Sales.Add(new SalesInfo()
{
SalesRecordId = item.SalesRecordId,
AgentName =
ctx.Agents.Where(id=>id.AgentId==item.AgentId).First().AgentName,
TerritoryName =
ctx.Territories.Where(id=>id.TerritoryId==item.TerritoryId).First().TerritoryName,
ProductName =
ctx.Products.Where(id=>id.ProductId==item.ProductId).First().ProductName,
Quantity = item.Quantity
});
}

return Sales;
}

/// <summary>
/// The Method works with Multiple Parameters in the URL
/// Here filter parameter is 'AND' or 'OR'
/// </summary>
/// <param name="agentId"></param>
/// <param name="filter"></param>
/// <param name="territoryId"></param>
/// <returns></returns>
[Route("Agents/{agentId}/{filter}/Territories/{territoryId}")]
public IEnumerable<SalesInfo> GetSales(int agentId,string filter,int territoryId)
{
List<SalesInfo> Sales = new List<SalesInfo>();
filter = filter.ToUpper();

switch (filter)
{
case "AND":
var result1 = from s in ctx.Sales
where s.AgentId == agentId && s.TerritoryId == territoryId
select new
{
SalesRecordId = s.SalesRecordId,
AgentId = s.AgentId,
TerritoryId = s.TerritoryId,
ProductId = s.ProductId,
Quantity = s.Quantity
};

foreach (var item in result1)


{
Sales.Add(new SalesInfo()
{
SalesRecordId = item.SalesRecordId,
AgentName = ctx.Agents.Where(id => id.AgentId ==
item.AgentId).First().AgentName,
TerritoryName = ctx.Territories.Where(id => id.TerritoryId ==
item.TerritoryId).First().TerritoryName,
ProductName = ctx.Products.Where(id => id.ProductId ==
item.ProductId).First().ProductName,
Quantity = item.Quantity
});
}

break;
case "OR":
var result2 = from s in ctx.Sales
where s.AgentId == agentId || s.TerritoryId == territoryId
select new
{
SalesRecordId = s.SalesRecordId,
AgentId = s.AgentId,
TerritoryId = s.TerritoryId,
ProductId = s.ProductId,
Quantity = s.Quantity
};

foreach (var item in result2)


{
Sales.Add(new SalesInfo()
{
SalesRecordId = item.SalesRecordId,
AgentName = ctx.Agents.Where(id => id.AgentId ==
item.AgentId).First().AgentName,
TerritoryName = ctx.Territories.Where(id => id.TerritoryId ==
item.TerritoryId).First().TerritoryName,
ProductName = ctx.Products.Where(id => id.ProductId ==
item.ProductId).First().ProductName,
Quantity = item.Quantity
});
}

break;
}

return Sales;
}
}
}
The above implementation is very important; the API controller class has all action methods for
HTTP GET operations. All the GET actions are differentiated using the Route Attributes applied
on them.

· The method ‘GetAgents()’ is applied with Route Attribute as [Route(“Agents”)], so the Url for
the method will be:

http://server/WebSite/Agents

· One of the major advantages of the Attribute Routing is the support provided for
multi-parameters passed to the action method. In the above class, the method GetSales()
accepts 3 parameters of name agentId, filter and territoryId which are of the type int, string, int
respectively. The Routing for this method is defined using

[Route("Agents/{agentId}/{filter}/Territories/{territoryId}")]

In the above route, the input parameters for the method are defined using the ‘{}’ expressions.
The Url for the GetSales() will look as below:
http://server/WebSite/Agents/1/AND/Territories/1

Here agentid is 1, filter is ‘AND’ and territoryId is 1. This means that for the specific AgentId, and
for a specific TerritoryId, the data will be retrieved based upon the filter value like All, AND, OR.

As per the Attribute Route applied on actions of the API controller class, the URL for action will
be as below:

Method Name

Attribute Route

URL

GetAgents()

[Route(Agents)]

http://Server/WebSite/Agents

GetTerritories()

[Route(Territories)]

http://Server/WebSite/Territories

GetSales()

[Route(SalesInfo)]

http://Server/WebSite/SalesInfo

GetSales()

[Route("Agents/{agentId}/{filter}/Territories/{territoryId}")]

http://Server/WebSites/Agents/1

/OR/Territories/1

Note: Filter can be ‘AND’, ‘All’, etc.


To support and enable the Attribute Routing for ASP.NET WEB API 2, the Register method from
the WebApiConfig class has been used as follows:

public static class WebApiConfig


{
public static void Register(HttpConfiguration config)
{
// Web API configuration and services

// Web API routes


config.MapHttpAttributeRoutes();

config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
Step 5: Using the Index Action method of the Home Controller, add a new Empty View in the
project. In this Index.cshtml add the following html:

<table id="tbl1">
<tr>
<td>
Agent
</td>
<td>
<select id="lstagents"></select>
</td>
<td>
Filter
</td>
<td>
<select id="lstoption">

</select>
</td>
<td>
Territory
</td>
<td>
<select id="lstterritories"></select>
</td>
</tr>
</table>
<div></div>

<table class="clstable">
<thead>
<tr>
<th class="clstable">SalesRecordId</th>
<th class="clstable">AgentName</th>
<th class="clstable">TerritoryName</th>
<th class="clstable">ProductName</th>
<th class="clstable">Quantity</th>
</tr>
</thead>
<tbody>
<tr>
<td class="clstable"> <span></span></td>
<td class="clstable"> <span></span></td>
<td class="clstable"> <span></span></td>
<td class="clstable"> <span></span></td>
<td class="clstable"> <span></span></td>
</tr>
</tbody>
</table>
Step 6: For this application to consume the WEB APIs, we will be using jQuery and Knockout
libraries. I am using Knockout because of it’s excellent databinding features. Add these libraries
in the project using NuGet Package Manager. In the Index.cshtml add the script references for
jQuery and Knockout.js and styles as shown here:

<script src="~/Scripts/jquery-2.1.1.min.js"></script>
<script src="~/Scripts/knockout-3.2.0.js"></script>

<style type="text/css">
.clstable{
border:double;
}
</style>

<script type="text/javascript">
var ViewModel = function (){
var self = this;

//Observable Arrays for Agents, Territories, Sales and Filters

self.Agents = ko.observableArray([]);
self.Territories = ko.observableArray([]);
self.Sales = ko.observableArray([]);
self.FilterOptions = ko.observableArray([
"All", "AND", "OR"
]);

//Observable declaration for Selected Agent, Territory and Filters

self.SelectedAgent = ko.observable();
self.SelectedTerritory = ko.observable();
self.SelectedFilter = ko.observable();

var filter;

loadagents();
loadterritories();

//The Function used to Load Agents


function loadagents() {
$.ajax({
url: "/Agents",
type: "GET"
}).done(function (resp) {
ko.utils.arrayForEach(resp, function (item) {
self.Agents.push({AgentId:item.AgentId,AgentName:item.AgentName});
});
}).error(function (err) {
alert("Error " + err.status + " " + err.statusText);
});
}

//The Function used to Load Terrotories


function loadterritories() {
$.ajax({
url: "/Territories",
type: "GET"
}).done(function (resp) {
ko.utils.arrayForEach(resp, function (item) {

self.Territories.push({TerritoryId:item.TerritoryId,TerritoryName:item.TerritoryName});
});
}).error(function (err) {
alert("Error " + err.status + " " + err.statusText);
});
}

self.SelectedAgent.subscribe(function (val) {

if (self.SelectedTerritory() !== 'undefined') {


loadSalesData(val, filter, self.SelectedTerritory());
}
else {
alert("Please Select the Territory Name");
}

});

self.SelectedTerritory.subscribe(function (val) {

if (self.SelectedAgent() !== 'undefined') {


loadSalesData(self.SelectedAgent(),filter,val);
}
else {
alert("Please Select the Agent Name");
}
});

self.SelectedFilter.subscribe(function (v) {
filter = v;

loadSalesData(self.SelectedAgent(), filter, self.SelectedTerritory());


});

//Function to load Sales Information


//If the filter is 'All' the complete Sales information will be loaded
//Else the Sales information based upon 'AND' and 'OR' condition combination of the
//Agent and territory will be loaded
function loadSalesData(agentId,filter,territoryId) {
var url;
if (filter === 'All') {
url = "/SalesInfo";
}
else {
url = "/Agents/" + agentId + "/" + filter + "/Territories/" + territoryId;
}

$.ajax({
url: url,
type:"GET"
}).done(function (resp) {
self.Sales(resp);
}).error(function (err) {
alert("Error " + err.status + " " + err.statusText);
});
}

};
ko.applyBindings(new ViewModel());
</script>
In the above JavaScript, the ViewModel code has the following specification:

· The code defines observable arrays for storing Agents, Territories, Sales and Filter Options.
The FilterOptions observable array defines search conditions e.g. ALL, will return all sales
records, whereas AND and OR return sales records based upon the logical conditions of Agent
and Territory.

· Functions ‘loadagents()’ and ‘loadterritories()’ will make call to WEB API and retrieve the
respective data from the server which will be pushed in the respective observable array.

· Function ‘loadSalesData()’ accepts agentId, filter and territoryId as input parameters. If the
filter is ‘All’ then all sales data will be retrieved using ‘/SalesInfo’ URL. If the value of the filter is
either ‘AND’ or ‘OR’ then the URL will be formed based upon the ‘AND’ or ‘OR’ combination of
agentId and territoryId and the sales data will be fetched.

Step 7: Since we have used Knockout library, we need to bind the Observables and
ObservableArray to HTML UI as below:

<table id="tbl1">
<tr>
<td>
Agent
</td>
<td>
<select id="lstagents" data-bind="options:Agents,optionsCaption:'Choose Agent
Name',value:SelectedAgent,optionsText:'AgentName',optionsValue:'AgentId'"></select>
</td>
<td>
Filter
</td>
<td>
<select id="lstoption" data-bind="options:FilterOptions,value:SelectedFilter">

</select>
</td>
<td>
Territory
</td>
<td>
<select id="lstterritories" data-bind="options:Territories,optionsCaption:'Choose Territory
Name',value:SelectedTerritory,optionsText:'TerritoryName',optionsValue:'TerritoryId'"></select>
</td>
</tr>
</table>
<div></div>

<table class="clstable">
<thead>
<tr>
<th class="clstable">SalesRecordId</th>
<th class="clstable">AgentName</th>
<th class="clstable">TerritoryName</th>
<th class="clstable">ProductName</th>
<th class="clstable">Quantity</th>
</tr>
</thead>
<tbody data-bind="foreach:Sales">
<tr>
<td class="clstable"> <span data-bind="text:SalesRecordId"></span></td>
<td class="clstable"> <span data-bind="text:AgentName"></span></td>
<td class="clstable"> <span data-bind="text:TerritoryName"></span></td>
<td class="clstable"> <span data-bind="text:ProductName"></span></td>
<td class="clstable"> <span data-bind="text:Quantity"></span></td>
</tr>
</tbody>
</table>
In the above code, the html < select > element is bound with the ObservableArray using
‘options’ binding, the value binding is set to the Observable declared in the ViewModel. The
optionsText and optionsValue corresponds to the selectedtext and selectedvalue from the <
select > element.

Step 8: Run the application and the result will be as seen here:

When the page is loaded, it will show all records from sales because the filter is set to value ‘All’
and the result will be as seen here:

filter-all

Select the AgentName and the TerritoryName from the List and change the Filter to ‘AND’, the
result will be as below:

sales-record-knockout-webapi

The above screenshot shows the sale by Agent Deepak in Maharashtra Territory.

Change the filter to OR, the result will be as below:

filter-all

Conclusion: The Attribute Routing provided with ASP.NET WEB API 2 makes it easy to define
clear URLs with multiple parameter for action methods. The major advantage here is that in one
API controller class, we can have multiple methods of same types (multiple HTTP Get etc.)
---------------------------------

This is the 3rd post in a series of ASP.NET MVC 4 Tutorials. The first two posts were on
ASP.NET MVC 4 Bundling and Minification and ASP.NET MVC 4 Entity Framework and Data
Migrations. In this tutorial I want to briefly look at the new Web API integration in ASP.NET MVC
4. Web API introduces a new route for API calls as well as an ApiController that responds to
Get, Post, Put, and Delete requests from REST Clients. Web API introduces formatters that can
do content negotiation via XML, JSON, etc. as well as provides better customization of the
response using HttpResponseMessage.
ASP.NET MVC 4 introduces several new project types after you initially pick that you want to
develop an ASP.NET MVC 4 Web Application. One of those application types is the new Web
API Project.

ASP.NET MVC 4 Web API Project

If you choose the Web API Project, a new Web API Controller Class is created for you to
provide an example of responding to Get, Post, Put, and Delete requests for your API.

public class ValuesController : ApiController {

// GET /api/values
public IEnumerable<string> Get() {
return new string[] { "value1", "value2" };
}

// GET /api/values/5
public string Get(int id) {
return "value";
}

// POST /api/values
public void Post(string value) {}

// PUT /api/values/5
public void Put(int id, string value) {}

// DELETE /api/values/5
public void Delete(int id) {}
}
With the Web API Project you will also notice a new API specific route added to the RouteTable
in Global.asax.cs.

routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
Running the project and navigating to ~/api/values will display a list of the values in XML
Format. I removed the XML namespacing to keep things simple.

<ArrayOfString>
<string>value1</string>
<string>value2</string>
</ArrayOfString>
If you change the Accept Header so that you will only accept JSON, the same controller action
will send the values via JSON instead.

["value1","value2"]
Creating a new Web API Controller Class is as simple as using the Add Controller Recipe in
ASP.NET MVC 4 and choosing the Empty API controller Tempate

Web API Controller Class in ASP.NET MVC 4

Or, you could just create one via Add Item which has a new Web API Controller Class as an
option.

I created a simple ProductsController that handles all the CRUD options for products in a
mythical e-commerce website.

public class ProductsController : ApiController {


private readonly IRepository<Product> _repository;

public ProductsController(IRepository<Product> repository) {


_repository = repository;
}

public IEnumerable<Product> Get() {


return _repository.Queryable();
}

public Product Get(int id) {


var product = _repository.Get(id);

if (product == null)
throw new HttpResponseException(HttpStatusCode.NotFound);

return product;
}

public HttpResponseMessage<Product> Post(Product product) {


_repository.Add(product);

var response = new HttpResponseMessage<Product>


(product, HttpStatusCode.Created);
response.Headers.Location = new Uri(Request.RequestUri,
Url.Route(null, new {id = product.Id}));

return response;
}

public Product Put(int id, Product product) {


var existingProduct = _repository.Get(id);

if (existingProduct == null)
throw new HttpResponseException(HttpStatusCode.NotFound);

_repository.Save(product);

return product;
}

public HttpResponseMessage Delete(int id) {


_repository.Delete(id);

return new HttpResponseMessage(HttpStatusCode.NoContent);


}
}
You can see that in some instances I am just returning a Product and in other instances I am
returning a more informational HttpResponseMessage. For example, in the case of the Post of a
new Product, I need to tell the REST Client the new location of the newly added product in the
header. In other actions I am also throwing a HttpResponseException if the resource requested
is not found. Validation, Logging, and other concerns are being done in various ActionFilters just
like in your normal ASP.NET MVC Projects. Try to pull those cross-cutting concerns out of the
main logic as much as possible.

If you want to enable various paging and querying of products you can make a slight change to
the Get ApiController Action and return an IQueryable<Product> as opposed to
IEnumerable<Product>.

public IQueryable<Product> Get() {


return _repository.Queryable();
}
Now from your browser you can add paging, filtering, sorting, and other options to shape the
data. Here is an example call that does paging and sorting.

api/products?$skip=2&$top=2&$orderby=Title
The XML Response by the browser is:
<ArrayOfProduct>
<Product>
<Id>3</Id>
<Title>RipStik</Title>
<Price>69.00</Price>
</Product>
<Product>
<Id>4</Id>
<Title>Shred Sled</Title>
<Price>49.00</Price>
</Product>
</ArrayOfProduct>
Or the JSON Response:

[{"Id":3,"Price":69.00,"Title":"RipStik"},
{"Id":4,"Price":49.00,"Title":"Shred Sled"}]
ASP.NET Web API integration with ASP.NET MVC 4 is really slick. Now you can easily create
an API for your website using the new ApiController Base Class to respond to REST Clients.
---------------------------------------------------------------------------------------------------------

**Authentication and Authorization


Authentication and Authorization in ASP.NET Web API
By Mike Wasson|November 27, 2012
889 of 983 people found this helpful
Print
You've created a web API, but now you want to control access to it. In this series of articles,
we'll look at some options for securing a web API from unauthorized users. This series will cover
both authentication and authorization.

Authentication is knowing the identity of the user. For example, Alice logs in with her username
and password, and the server uses the password to authenticate Alice.
Authorization is deciding whether a user is allowed to perform an action. For example, Alice has
permission to get a resource but not create a resource.
The first article in the series gives a general overview of authentication and authorization in
ASP.NET Web API. Other topics describe common authentication scenarios for Web API.

Thanks to the people who reviewed this series and provided valuable feedback: Rick Anderson,
Levi Broderick, Barry Dorrans, Tom Dykstra, Hongmei Ge, David Matson, Daniel Roth, Tim
Teebken.

Authentication
Web API assumes that authentication happens in the host. For web-hosting, the host is IIS,
which uses HTTP modules for authentication. You can configure your project to use any of the
authentication modules built in to IIS or ASP.NET, or write your own HTTP module to perform
custom authentication.

When the host authenticates the user, it creates a principal, which is an IPrincipal object that
represents the security context under which code is running. The host attaches the principal to
the current thread by setting Thread.CurrentPrincipal. The principal contains an associated
Identity object that contains information about the user. If the user is authenticated, the
Identity.IsAuthenticated property returns true. For anonymous requests, IsAuthenticated returns
false. For more information about principals, see Role-Based Security.

HTTP Message Handlers for Authentication

Instead of using the host for authentication, you can put authentication logic into an HTTP
message handler. In that case, the message handler examines the HTTP request and sets the
principal.

When should you use message handlers for authentication? Here are some tradeoffs:

An HTTP module sees all requests that go through the ASP.NET pipeline. A message handler
only sees requests that are routed to Web API.
You can set per-route message handlers, which lets you apply an authentication scheme to a
specific route.
HTTP modules are specific to IIS. Message handlers are host-agnostic, so they can be used
with both web-hosting and self-hosting.
HTTP modules participate in IIS logging, auditing, and so on.
HTTP modules run earlier in the pipeline. If you handle authentication in a message handler, the
principal does not get set until the handler runs. Moreover, the principal reverts back to the
previous principal when the response leaves the message handler.
Generally, if you don't need to support self-hosting, an HTTP module is a better option. If you
need to support self-hosting, consider a message handler.

Setting the Principal

If your application performs any custom authentication logic, you must set the principal on two
places:

Thread.CurrentPrincipal. This property is the standard way to set the thread's principal in .NET.
HttpContext.Current.User. This property is specific to ASP.NET.
The following code shows how to set the principal:

private void SetPrincipal(IPrincipal principal)


{
Thread.CurrentPrincipal = principal;
if (HttpContext.Current != null)
{
HttpContext.Current.User = principal;
}
}
For web-hosting, you must set the principal in both places; otherwise the security context may
become inconsistent. For self-hosting, however, HttpContext.Current is null. To ensure your
code is host-agnostic, therefore, check for null before assigning to HttpContext.Current, as
shown.

Authorization

Authorization happens later in the pipeline, closer to the controller. That lets you make more
granular choices when you grant access to resources.

Authorization filters run before the controller action. If the request is not authorized, the filter
returns an error response, and the action is not invoked.
Within a controller action, you can get the current principal from the ApiController.User property.
For example, you might filter a list of resources based on the user name, returning only those
resources that belong to that user.

Using the [Authorize] Attribute

Web API provides a built-in authorization filter, AuthorizeAttribute. This filter checks whether the
user is authenticated. If not, it returns HTTP status code 401 (Unauthorized), without invoking
the action.

You can apply the filter globally, at the controller level, or at the level of inidivual actions.

Globally: To restrict access for every Web API controller, add the AuthorizeAttribute filter to the
global filter list:

public static void Register(HttpConfiguration config)


{
config.Filters.Add(new AuthorizeAttribute());
}
Controller: To restrict access for a specific controller, add the filter as an attribute to the
controller:

// Require authorization for all actions on the controller.


[Authorize]
public class ValuesController : ApiController
{
public HttpResponseMessage Get(int id) { ... }
public HttpResponseMessage Post() { ... }
}
Action: To restrict access for specific actions, add the attribute to the action method:

public class ValuesController : ApiController


{
public HttpResponseMessage Get() { ... }

// Require authorization for a specific action.


[Authorize]
public HttpResponseMessage Post() { ... }
}
Alternatively, you can restrict the controller and then allow anonymous access to specific
actions, by using the [AllowAnonymous] attribute. In the following example, the Post method is
restricted, but the Get method allows anonymous access.

[Authorize]
public class ValuesController : ApiController
{
[AllowAnonymous]
public HttpResponseMessage Get() { ... }

public HttpResponseMessage Post() { ... }


}
In the previous examples, the filter allows any authenticated user to access the restricted
methods; only anonymous users are kept out. You can also limit access to specific users or to
users in specific roles:

// Restrict by user:
[Authorize(Users="Alice,Bob")]
public class ValuesController : ApiController
{
}

// Restrict by role:
[Authorize(Roles="Administrators")]
public class ValuesController : ApiController
{
}
The AuthorizeAttribute filter for Web API controllers is located in the System.Web.Http
namespace. There is a similar filter for MVC controllers in the System.Web.Mvc namespace,
which is not compatible with Web API controllers.

Custom Authorization Filters

To write a custom authorization filter, derive from one of these types:

AuthorizeAttribute. Extend this class to perform authorization logic based on the current user
and the user’s roles.
AuthorizationFilterAttribute. Extend this class to perform synchronous authorization logic that is
not necessarily based on the current user or role.
IAuthorizationFilter. Implement this interface to perform asynchronous authorization logic; for
example, if your authorization logic makes asynchronous I/O or network calls. (If your
authorization logic is CPU-bound, it is simpler to derive from AuthorizationFilterAttribute,
because then you don’t need to write an asynchronous method.)
The following diagram shows the class hierarchy for the AuthorizeAttribute class.

Authorization Inside a Controller Action

In some cases, you might allow a request to proceed, but change the behavior based on the
principal. For example, the information that you return might change depending on the user’s
role. Within a controller method, you can get the current principle from the ApiController.User
property.

public HttpResponseMessage Get()


{
if (User.IsInRole("Administrators"))
{
// ...
}
}
-----------------------

Token Based Authentication in Web API 2


By Rajeev Ranjan on Jan 01, 2015
This article explains the OWIN OAuth 2.0 Authorization and how to implement an OAuth 2.0
Authorization server using the OWIN OAuth middleware.
150.4k
12
4
facebook
twitter
linkedIn
google Plus
Reddit
expand
Download 100% FREE Spire Office APIs
Introduction

This article explains the OWIN OAuth 2.0 Authorization and how to implement an OAuth 2.0
Authorization server using the OWIN OAuth middleware.

The OAuth 2.0 Authorization framwork is defined in RFC 6749. It enables third-party
applications to obtain limited access to HTTP services, either on behalf of a resource owner by
producing a desired effect on approval interaction between the resource owner and the HTTP
service or by allowing the third-party application to obtain access on its own behalf.

Now let us talk about how OAuth 2.0 works. It supports the following two (2) different
authentication variants:

Three-Legged
Two-Legged
Three-Legged Approach: In this approach, a resource owner (user) can assure a third-party
client (mobile applicant) about the identity, using a content provider (OAuthServer) without
sharing any credentials to the third-party client.

Two-Legged Approach: This approach is known as a typical client-server approach where the
client can directly authenticate the user with the content provider.

Multiple classes are in OAuth Authorization

OAuth Authorization can be done using the following two classes:

IOAuthorizationServerProvider
OAuthorizationServerOptions
IOAuthorizationServerProvider

It extends the abstract AuthenticationOptions from Microsoft.Owin.Security and is used by the


core server options such as:

Enforcing HTTPS
Error detail level
Token expiry
Endpoint paths
We can use the IOAuthorizationServerProvider class to control the security of the data
contained in the access tokens and authorization codes. System.Web will use machine key data
protection, whereas HttpListener will rely on the Data Protection Application Programming
Interface (DPAPI). We can see the various methods in this class.

IOAuthAuthorizationServerProvider

OAuthorizationServerOptions

IOAuthAuthorizationServerProvider is responsible for processing events raised by the


authorization server. Katana ships with a default implementation of
IOAuthAuthorizationServerProvider called OAuthAuthorizationServerProvider. It is a very simple
starting point for configuring the authorization server, since it allows us to either attach individual
event handlers or to inherit from the class and override the relevant method directly. We can
see the various methods in this class.

OAuthAuthorizationServerOptions

From now we can start to learn how to build an application having token-based authentication.

Step 1

Open the Visual Studio 2013 and click New Project.

Step 2

Select the Console based application and provide a nice name for the project.

NewProject
Step 3

Create a Token class and Add some Property.

public class Token


{
[JsonProperty("access_token")]
public string AccessToken { get; set; }

[JsonProperty("token_type")]
public string TokenType { get; set; }

[JsonProperty("expires_in")]
public int ExpiresIn { get; set; }

[JsonProperty("refresh_token")]
public string RefreshToken { get; set; }
}
Step 4
Create a startup class and use the IOAuthorizationServerProvider class as well as the
OAuthorizationServerOptions class and set the dummy password and username. I have also
set the default TokenEndpoint and TokenExpire time.

public class Startup


{
public void Configuration(IAppBuilder app)
{
var oauthProvider = new OAuthAuthorizationServerProvider
{
OnGrantResourceOwnerCredentials = async context =>
{
if (context.UserName == "rranjan" && context.Password == "password@123")
{
var claimsIdentity = new ClaimsIdentity(context.Options.AuthenticationType);
claimsIdentity.AddClaim(new Claim("user", context.UserName));
context.Validated(claimsIdentity);
return;
}
context.Rejected();
},
OnValidateClientAuthentication = async context =>
{
string clientId;
string clientSecret;
if (context.TryGetBasicCredentials(out clientId, out clientSecret))
{
if (clientId == "rajeev" && clientSecret == "secretKey")
{
context.Validated();
}
}
}
};
var oauthOptions = new OAuthAuthorizationServerOptions
{
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/accesstoken"),
Provider = oauthProvider,
AuthorizationCodeExpireTimeSpan= TimeSpan.FromMinutes(1),
AccessTokenExpireTimeSpan=TimeSpan.FromMinutes(3),
SystemClock= new SystemClock()

};
app.UseOAuthAuthorizationServer(oauthOptions);
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());

var config = new HttpConfiguration();


config.MapHttpAttributeRoutes();
app.UseWebApi(config);
}
}
Step 5

Add a controller inherited from API controller.

[Authorize]
public class TestController : ApiController
{
[Route("test")]
public HttpResponseMessage Get()
{
return Request.CreateResponse(HttpStatusCode.OK, "hello from a secured resource!");
}
}
Step 6

Now check the authorization on the basis of the token, so in the Program class validate it.

static void Main()


{
string baseAddress = "http://localhost:9000/";

// Start OWIN host


using (WebApp.Start<Startup>(url: baseAddress))
{
var client = new HttpClient();
var response = client.GetAsync(baseAddress + "test").Result;
Console.WriteLine(response);
Console.WriteLine();

var authorizationHeader =
Convert.ToBase64String(Encoding.UTF8.GetBytes("rajeev:secretKey"));
client.DefaultRequestHeaders.Authorization = new
AuthenticationHeaderValue("Basic", authorizationHeader);

var form = new Dictionary<string, string>


{
{"grant_type", "password"},
{"username", "rranjan"},
{"password", "password@123"},
};

var tokenResponse = client.PostAsync(baseAddress + "accesstoken", new


FormUrlEncodedContent(form)).Result;
var token = tokenResponse.Content.ReadAsAsync<Token>(new[] { new
JsonMediaTypeFormatter() }).Result;

Console.WriteLine("Token issued is: {0}", token.AccessToken);

Console.WriteLine();

client.DefaultRequestHeaders.Authorization = new
AuthenticationHeaderValue("Bearer", token.AccessToken);
var authorizedResponse = client.GetAsync(baseAddress + "test").Result;
Console.WriteLine(authorizedResponse);
Console.WriteLine(authorizedResponse.Content.ReadAsStringAsync().Result);
}

Console.ReadLine();
}
Output

When all the authentication of username and password is not correct then it doesn't generate
the token.
authorizationWebAPI

When the Authentication is passed we get success and we get a token.

successTokenWebAPI
Summary

In this article we have understand the token-based authentication in Web API 2. I hope you will
like it.
-------------------------------------------------------------------------------------------------------------
Cors​:

List

Enabling Cross-Origin Requests in ASP.NET Web API 2


By Mike Wasson|July 15, 2014
801 of 897 people found this helpful
Print
Browser security prevents a web page from making AJAX requests to another domain. This
restriction is called the same-origin policy, and prevents a malicious site from reading sentitive
data from another site. However, sometimes you might want to let other sites call your web API.

Cross Origin Resource Sharing (CORS) is a W3C standard that allows a server to relax the
same-origin policy. Using CORS, a server can explicitly allow some cross-origin requests while
rejecting others. CORS is safer and more flexible than earlier techniques such as JSONP. This
tutorial shows how to enable CORS in your Web API application.

Software versions used in the tutorial

Introduction
Create the WebService Project
Create the WebClient Project
Enable CORS in Web API
How CORS Works
Scope Rules for [EnableCors]
Set the Allowed Origins
Set the Allowed HTTP Methods
Set the Allowed Request Headers
Set the Allowed Response Headers
Passing Credentials in Cross-Origin Requests
Custom CORS Policy Providers
Browser Support
Introduction

This tutorial demonstrates CORS support in ASP.NET Web API. We’ll start by creating two
ASP.NET projects – one called “WebService”, which hosts a Web API controller, and the other
called “WebClient”, which calls WebService. Because the two applications are hosted at
different domains, an AJAX request from WebClient to WebService is a cross-origin request.
What is "Same Origin"?

Two URLs have the same origin if they have identical schemes, hosts, and ports. (RFC 6454)

These two URLs have the same origin:

http://example.com/foo.html
http://example.com/bar.html
These URLs have different origins than the previous two:

http://example.net - Different domain


http://example.com:9000/foo.html - Different port
https://example.com/foo.html - Different scheme
http://www.example.com/foo.html - Different subdomain
Internet Explorer does not consider the port when comparing origins.

Create the WebService Project

This section assumes you already know how to create Web API projects. If not, see Getting
Started with ASP.NET Web API.

Start Visual Studio and create a new ASP.NET Web Application project. Select the Empty
project template. Under “Add folders and core references for”, select the Web API checkbox.
Optionally, select the "Host in Cloud" option to deploy the app to Mircosoft Azure. Microsoft
offers free web hosting for up to 10 websites in a free Azure trial account.

Add a Web API controller named TestController with the following code:

using System.Net.Http;
using System.Web.Http;

namespace WebService.Controllers
{
public class TestController : ApiController
{
public HttpResponseMessage Get()
{
return new HttpResponseMessage()
{
Content = new StringContent("GET: Test message")
};
}

public HttpResponseMessage Post()


{
return new HttpResponseMessage()
{
Content = new StringContent("POST: Test message")
};
}

public HttpResponseMessage Put()


{
return new HttpResponseMessage()
{
Content = new StringContent("PUT: Test message")
};
}
}
}
You can run the application locally or deploy to Azure. (For the screenshots in this tutorial, I
deployed to Azure App Service Web Apps.) To verify that the web API is working, navigate to
http://hostname/api/test/, where hostname is the domain where you deployed the application.
You should see the response text, "GET: Test Message".

Create the WebClient Project

Create another ASP.NET Web Application project and select the MVC project template.
Optionally, select Change Authentication > No Authentication. You don't need authentication for
this tutorial.

In Solution Explorer, open the file Views/Home/Index.cshtml. Replace the code in this file with
the following:

<div>
<select id="method">
<option value="get">GET</option>
<option value="post">POST</option>
<option value="put">PUT</option>
</select>
<input type="button" value="Try it" onclick="sendRequest()" />
<span id='value1'>(Result)</span>
</div>

@section scripts {
<script>
// TODO: Replace with the URL of your WebService app
var serviceUrl = 'http://mywebservice/api/test';

function sendRequest() {
var method = $('#method').val();

$.ajax({
type: method,
url: serviceUrl
}).done(function (data) {
$('#value1').text(data);
}).error(function (jqXHR, textStatus, errorThrown) {
$('#value1').text(jqXHR.responseText || textStatus);
});
}
</script>
}
For the serviceUrl variable, use the URI of the WebService app. Now run the WebClient app
locally or publish it to another website.

Clicking the “Try It” button submits an AJAX request to the WebService app, using the HTTP
method listed in the dropdown box (GET, POST, or PUT). This lets us examine different
cross-origin requests. Right now, the WebService app does not support CORS, so if you click
the button, you will get an error.

If you watch the HTTP traffic in a tool like Fiddler, you will see that the browser does send the
GET request, and the request succeeds, but the AJAX call returns an error. It’s important to
understand that same-origin policy does not prevent the browser from sending the request.
Instead, it prevents the application from seeing the response.
Enable CORS

Now let's enable CORS in the WebService app. First, add the CORS NuGet package. In Visual
Studio, from the Tools menu, select Library Package Manager, then select Package Manager
Console. In the Package Manager Console window, type the following command:

Install-Package Microsoft.AspNet.WebApi.Cors
This command installs the latest package and updates all dependencies, including the core
Web API libraries. User the -Version flag to target a specific version. The CORS package
requires Web API 2.0 or later.

Open the file App_Start/WebApiConfig.cs. Add the following code to the WebApiConfig.Register
method.

using System.Web.Http;
namespace WebService
{
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// New code
config.EnableCors();

config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
}
Next, add the [EnableCors] attribute to the TestController class:

using System.Net.Http;
using System.Web.Http;
using System.Web.Http.Cors;

namespace WebService.Controllers
{
[EnableCors(origins: "http://mywebclient.azurewebsites.net", headers: "*", methods: "*")]
public class TestController : ApiController
{
// Controller methods not shown...
}
}
For the origins parameter, use the URI where you deployed the WebClient application. This
allows cross-origin requests from WebClient, while still disallowing all other cross-domain
requests. Later, I’ll describe the parameters for [EnableCors] in more detail.

Do not include a forward slash at the end of the origins URL.

Redeploy the updated WebService application. You don't need to update WebClient. Now the
AJAX request from WebClient should succeed. The GET, PUT, and POST methods are all
allowed.

How CORS Works

This section describes what happens in a CORS request, at the level of the HTTP messages.
It’s important to understand how CORS works, so that you can configure the [EnableCors]
attribute correctly, and troubleshoot if things don’t work as you expect.

The CORS specification introduces several new HTTP headers that enable cross-origin
requests. If a browser supports CORS, it sets these headers automatically for cross-origin
requests; you don’t need to do anything special in your JavaScript code.

Here is an example of a cross-origin request. The “Origin” header gives the domain of the site
that is making the request.

GET http://myservice.azurewebsites.net/api/test HTTP/1.1


Referer: http://myclient.azurewebsites.net/
Accept: */*
Accept-Language: en-US
Origin: http://myclient.azurewebsites.net
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)
Host: myservice.azurewebsites.net
If the server allows the request, it sets the Access-Control-Allow-Origin header. The value of this
header either matches the Origin header, or is the wildcard value “*”, meaning that any origin is
allowed.

HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Type: text/plain; charset=utf-8
Access-Control-Allow-Origin: http://myclient.azurewebsites.net
Date: Wed, 05 Jun 2013 06:27:30 GMT
Content-Length: 17

GET: Test message


If the response does not include the Access-Control-Allow-Origin header, the AJAX request
fails. Specifically, the browser disallows the request. Even if the server returns a successful
response, the browser does not make the response available to the client application.

Preflight Requests

For some CORS requests, the browser sends an additional request, called a “preflight request”,
before it sends the actual request for the resource.

The browser can skip the preflight request if the following conditions are true:

The request method is GET, HEAD, or POST, and


The application does not set any request headers other than Accept, Accept-Language,
Content-Language, Content-Type, or Last-Event-ID, and
The Content-Type header (if set) is one of the following:
application/x-www-form-urlencoded
multipart/form-data
text/plain
The rule about request headers applies to headers that the application sets by calling
setRequestHeader on the XMLHttpRequest object. (The CORS specification calls these “author
request headers”.) The rule does not apply to headers the browser can set, such as User-Agent,
Host, or Content-Length.

Here is an example of a preflight request:

OPTIONS http://myservice.azurewebsites.net/api/test HTTP/1.1


Accept: */*
Origin: http://myclient.azurewebsites.net
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: accept, x-my-custom-header
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)
Host: myservice.azurewebsites.net
Content-Length: 0
The pre-flight request uses the HTTP OPTIONS method. It includes two special headers:

Access-Control-Request-Method: The HTTP method that will be used for the actual request.
Access-Control-Request-Headers: A list of request headers that the application set on the
actual request. (Again, this does not include headers that the browser sets.)
Here is an example response, assuming that the server allows the request:

HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Length: 0
Access-Control-Allow-Origin: http://myclient.azurewebsites.net
Access-Control-Allow-Headers: x-my-custom-header
Access-Control-Allow-Methods: PUT
Date: Wed, 05 Jun 2013 06:33:22 GMT
The response includes an Access-Control-Allow-Methods header that lists the allowed methods,
and optionally an Access-Control-Allow-Headers header, which lists the allowed headers. If the
preflight request succeeds, the browser sends the actual request, as described earlier.

Scope Rules for [EnableCors]

You can enable CORS per action, per controller, or globally for all Web API controllers in your
application.

Per Action

To enable CORS for a single action, set the [EnableCors] attribute on the action method. The
following example enables CORS for the GetItem method only.

public class ItemsController : ApiController


{
public HttpResponseMessage GetAll() { ... }

[EnableCors(origins: "http://www.example.com", headers: "*", methods: "*")]


public HttpResponseMessage GetItem(int id) { ... }

public HttpResponseMessage Post() { ... }


public HttpResponseMessage PutItem(int id) { ... }
}
Per Controller

If you set [EnableCors] on the controller class, it applies to all the actions on the controller. To
disable CORS for an action, add the [DisableCors] attribute to the action. The following example
enables CORS for every method except PutItem.

[EnableCors(origins: "http://www.example.com", headers: "*", methods: "*")]


public class ItemsController : ApiController
{
public HttpResponseMessage GetAll() { ... }
public HttpResponseMessage GetItem(int id) { ... }
public HttpResponseMessage Post() { ... }

[DisableCors]
public HttpResponseMessage PutItem(int id) { ... }
}

Globally

To enable CORS for all Web API controllers in your application, pass an EnableCorsAttribute
instance to the EnableCors method:

public static class WebApiConfig


{
public static void Register(HttpConfiguration config)
{
var cors = new EnableCorsAttribute("www.example.com", "*", "*");
config.EnableCors(cors);
// ...
}
}
If you set the attribute at more than one scope, the order of precedence is:

Action
Controller
Global
Set the Allowed Origins

The origins parameter of the [EnableCors] attribute specifies which origins are allowed to
access the resource. The value is a comma-separated list of the allowed origins.

[EnableCors(origins: "http://www.contoso.com,http://www.example.com",
headers: "*", methods: "*")]
You can also use the wildcard value “*” to allow requests from any origins.

Consider carefully before allowing requests from any origin. It means that literally any website
can make AJAX calls to your web API.

// Allow CORS for all origins. (Caution!)


[EnableCors(origins: "*", headers: "*", methods: "*")]
Set the Allowed HTTP Methods

The methods parameter of the [EnableCors] attribute specifies which HTTP methods are
allowed to access the resource. To allow all methods, use the wildcard value “*”. The following
example allows only GET and POST requests.

[EnableCors(origins: "http://www.example.com", headers: "*", methods: "get,post")]


public class TestController : ApiController
{
public HttpResponseMessage Get() { ... }
public HttpResponseMessage Post() { ... }
public HttpResponseMessage Put() { ... }
}
Set the Allowed Request Headers

Earlier I described how a preflight request might include an Access-Control-Request-Headers


header, listing the HTTP headers set by the application (the so-called “author request headers”).
The headers parameter of the [EnableCors] attribute specifies which author request headers are
allowed. To allow any headers, set headers to “*”. To whitelist specific headers, set headers to a
comma-separated list of the allowed headers:

[EnableCors(origins: "http://example.com",
headers: "accept,content-type,origin,x-my-header", methods: "*")]
However, browsers are not entirely consistent in how they set
Access-Control-Request-Headers. For example, Chrome currently includes “origin”; while
FireFox does not include standard headers such as “Accept”, even when the application sets
them in script.

If you set headers to anything other than “*”, you should include at least “accept”, “content-type”,
and “origin”, plus any custom headers that you want to support.

Set the Allowed Response Headers

By default, the browser does not expose all of the response headers to the application. The
response headers that are available by default are:

Cache-Control
Content-Language
Content-Type
Expires
Last-Modified
Pragma
The CORS spec calls these simple response headers. To make other headers available to the
application, set the exposedHeaders parameter of [EnableCors].

In the following example, the controller’s Get method sets a custom header named
‘X-Custom-Header’. By default, the browser will not expose this header in a cross-origin request.
To make the header available, include ‘X-Custom-Header’ in exposedHeaders.

[EnableCors(origins: "*", headers: "*", methods: "*", exposedHeaders: "X-Custom-Header")]


public class TestController : ApiController
{
public HttpResponseMessage Get()
{
var resp = new HttpResponseMessage()
{
Content = new StringContent("GET: Test message")
};
resp.Headers.Add("X-Custom-Header", "hello");
return resp;
}
}

Passing Credentials in Cross-Origin Requests

Credentials require special handling in a CORS request. By default, the browser does not send
any credentials with a cross-origin request. Credentials include cookies as well as HTTP
authentication schemes. To send credentials with a cross-origin request, the client must set
XMLHttpRequest.withCredentials to true.

Using XMLHttpRequest directly:

var xhr = new XMLHttpRequest();


xhr.open('get', 'http://www.example.com/api/test');
xhr.withCredentials = true;
In jQuery:

$.ajax({
type: 'get',
url: 'http://www.example.com/api/test',
xhrFields: {
withCredentials: true
}
In addition, the server must allow the credentials. To allow cross-origin credentials in Web API,
set the SupportsCredentials property to true on the [EnableCors] attribute:
[EnableCors(origins: "http://myclient.azurewebsites.net", headers: "*",
methods: "*", SupportsCredentials = true)]
If this property is true, the HTTP response will include an Access-Control-Allow-Credentials
header. This header tells the browser that the server allows credentials for a cross-origin
request.

If the browser sends credentials, but the response does not include a valid
Access-Control-Allow-Credentials header, the browser will not expose the response to the
application, and the AJAX request fails.

Be very careful about setting SupportsCredentials to true, because it means a website at


another domain can send a logged-in user’s credentials to your Web API on the user’s behalf,
without the user being aware. The CORS spec also states that setting origins to "*" is invalid if
SupportsCredentials is true.

Custom CORS Policy Providers

The [EnableCors] attribute implements the ICorsPolicyProvider interface. You can provide your
own implementation by creating a class that derives from Attribute and implements
ICorsProlicyProvider.

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false)]


public class MyCorsPolicyAttribute : Attribute, ICorsPolicyProvider
{
private CorsPolicy _policy;

public MyCorsPolicyAttribute()
{
// Create a CORS policy.
_policy = new CorsPolicy
{
AllowAnyMethod = true,
AllowAnyHeader = true
};

// Add allowed origins.


_policy.Origins.Add("http://myclient.azurewebsites.net");
_policy.Origins.Add("http://www.contoso.com");
}

public Task<CorsPolicy> GetCorsPolicyAsync(HttpRequestMessage request)


{
return Task.FromResult(_policy);
}
}
Now you can apply the attribute any place that you would put [EnableCors].

[MyCorsPolicy]
public class TestController : ApiController
{
.. //
For example, a custom CORS policy provider could read the settings from a configuration file.

As an alternative to using attributes, you can register an ICorsPolicyProviderFactory object that


creates ICorsPolicyProvider objects.

public class CorsPolicyFactory : ICorsPolicyProviderFactory


{
ICorsPolicyProvider _provider = new MyCorsPolicyProvider();

public ICorsPolicyProvider GetCorsPolicyProvider(HttpRequestMessage request)


{
return _provider;
}
}
To set the ICorsPolicyProviderFactory, call the SetCorsPolicyProviderFactory extension method
at startup, as follows:

public static class WebApiConfig


{
public static void Register(HttpConfiguration config)
{
config.SetCorsPolicyProviderFactory(new CorsPolicyFactory());
config.EnableCors();

// ...
}
}

Browser Support

The Web API CORS package is a server-side technology. The user's browser also needs to
support CORS. Fortunately, the current versions of all major browsers include support for
CORS.
Internet Explorer 8 and Internet Explorer 9 have partial support for CORS, using the legacy
XDomainRequest object instead of XMLHttpRequest. For more information, see
XDomainRequest - Restrictions, Limitations and Workarounds.
---------------------

XDomainRequest – Restrictions, Limitations and Workarounds


★★★★★★★★★★★★★★★
EricLaw [ex-MSFT]May 13, 201044
0
0
0
Update: Internet Explorer 10+ supports CORS using XMLHTTPRequest. IE11 deprecates the
XDomainRequest object and it is not available in IE11 Edge mode.

In Internet Explorer 8, the XDomainRequest object was introduced. This object allows AJAX
applications to make safe cross-origin requests directly by ensuring that HTTP Responses can
only be read by the current page if the data source indicates that the response is public; in that
way, the Same Origin Policy security guarantee is protected. Responses indicate their
willingness to allow cross domain access by including the Access-Control-Allow-Origin HTTP
response header with value *, or the exact origin of the calling page.

When designing the new object, our top priority was to ensure that existing sites and services
would not be put at risk. To that end, we imposed a number of restrictions on what sort of
requests can be made with the XDomainRequest object. Most of the restrictions are designed to
help prevent Cross-Site Request Forgery (CSRF) attacks against legacy services.

The restrictions and the reasoning behind them are described by the rest of this post.

1. The target URL must be accessed using the HTTP or HTTPS protocols.

This one is simple—because the object relies on a HTTP response header for access control,
the object requires that the target URL be HTTP or HTTPS so that it can examine the response
headers to obtain permission to make the response available to the caller.

2. The target URL must be accessed using only the HTTP methods GET and POST

In order to ensure that the new object did not increase the attack surface against existing
servers and services, we elected to restrict the HTTP methods (verbs) it may call to GET and
POST. HTML 4.01 forms are restricted to these same methods, which means that any service
which is at risk from the XDomainRequest object would also be vulnerable to attack from a
cross-origin HTML Form. Since HTML Forms have existed for well over a decade, it’s assumed
that applications have been hardened against attack from the GET and POST methods.
We could not assume that requests issued using other methods would be similarly handled by
servers. Beyond that concern, most other methods that developers would hope to use (e.g.
WebDAV / REST methods) also require sending custom HTTP Headers, and:

3. No custom headers may be added to the request

This restriction is similar to #2; we wanted to ensure that the XDomainRequest object would not
allow an attacker to issue a request that a HTML Form could not issue. This is important
because the Access-Control-Allow-Origin header isn’t available until after the response is
returned, so there’s no way to tell before the request is issued whether or not the server is
willing to accept cross-domain HTTP requests. Without these restrictions, a “Fire and Forget”
CSRF attack could take place against a legacy server, even if the server doesn’t return the
Access-Control-Allow-Origin header.

All XDomainRequest-issued requests are sent with an Origin header, indicating the Origin
(scheme+hostname) of the caller.

4. Only text/plain is supported for the request’s Content-Type header

In the original incarnation of the XDomainRequest object, we allowed specification of the


Content-Type for a POST request. It was pointed out that this violated our goal of emitting only
requests that HTML Forms can issue, because HTML Forms are limited to sending data in three
different content types: text/plain, application/x-www-urlencoded, and multipart/form-data. In
particular, it was pointed out that some AJAX server libraries would blindly assume that if they
received a request with a SOAP or JSON Content-Type, then the client must either be trusted or
Same Origin (because HTML itself previously offered no way to issue cross-origin requests with
that Content-Type).

Unfortunately, when we fixed this problem in a later IE8 Beta, we went a bit too far; we restricted
the content type to text/plain but didn’t allow the caller to specify that the data was in
application/x-www-urlencoded form. This is problematic because server-side frameworks (e.g.
ASP, ASPNET, etc) will only automatically parse a request’s fields into name-value pairs if the
x-www-urlencoded content type is specified.

Note: As of 2014, XDomainRequest doesn’t appear to send any Content-Type header at all. It’s
not clear to me when this changed.

To workaround this issue, server code that currently processes HTML Forms must be rewritten
to manually parse the request body into name-value pairs when receiving requests from
XDomainRequest objects. This makes adding support for the XDomainRequest object more
difficult than it would be otherwise.

5. No authentication or cookies will be sent with the request


In order to prevent misuse of the user’s ambient authority (e.g. cookies, HTTP credentials, client
certificates, etc), the request will be stripped of cookies and credentials and will ignore any
authentication challenges or Set-Cookie directives in the HTTP response. XDomainRequests
will not be sent on previously-authenticated connections, because some Windows
authentication protocols (e.g. NTLM/Kerberos) are per-connection-based rather than
per-request-based.

Sites that wish to perform authentication of the user for cross-origin requests can use explicit
methods (e.g. tokens in the POST body or URL) to pass this authentication information without
risking the user’s ambient authority.

6. Requests targeted to Intranet URLs may only be made from the Intranet Zone

As the table in the documentation shows, XDomainRequest restricts Internet-Zone pages from
making requests to Local Intranet-based resources. This security precaution isn’t directly
enforced by HTML Forms, but Internet Explorer’s Zone Elevation security feature provides a
similar protection for navigations, of which Form Submissions are simply a specialized type.

7. Requests must be targeted to the same scheme as the hosting page

This restriction means that if your AJAX page is at http://example.com, then your target URL
must also begin with HTTP. Similarly, if your AJAX page is at https://example.com, then your
target URL must also begin with HTTPS.

It was definitely our intent to prevent HTTPS pages from making XDomainRequests for
HTTP-based resources, as that scenario presents a Mixed Content Security Threat which many
developers and most users do not understand.

However, this restriction is overly broad, because it prevents HTTP pages from issuing
XDomainRequests targeted to HTTPS pages. While it’s true that the HTTP page itself may have
been compromised, there’s no reason that it should be forbidden from receiving public
resources securely.

Worst of all, the Same Scheme restriction means that web developers testing their pages locally
using the file:// scheme will find that all of the XDomainRequests are blocked because file://
doesn’t match either http:// or https://, which are the only valid target schemes (point #1). To
workaround this issue, web developers must host their pages on a local web server (e.g. IIS, the
Visual Studio hosting server, etc).

To workaround this limitation, you can build a postMessage-Proxy-for-XDR.


Despite the restrictions and unintended limitations, the XDomainRequest object provides
powerful functionality. As servers that support the CORS specification become more common,
the object will only get more useful.

Update: Internet Explorer 10 now supports CORS using XMLHTTPRequest which should be
preferred to the now-deprecated XDomainRequest object.

-Eric

Note: We intended to support COMET-streaming with XDomainRequest, but AJAX developers


may need to workaround one small bug in the object’s support for streaming responses.

Note: In IE8, all XDomainRequests will fail with an error when the user is browsing in InPrivate
Browsing mode. This bug was fixed in Internet Explorer 9.
----------------

ASP.NET Web API - CORS Support in ASP.NET Web API 2


By Brock Allen | December 2013

Cross-origin resource sharing (CORS) is a World Wide Web Consortium (W3C) specification
(commonly considered part of HTML5) that lets JavaScript overcome the same-origin policy
security restriction imposed by browsers. The same-origin policy means that your JavaScript
can only make AJAX calls back to the same origin of the containing Web page (where “origin” is
defined as the combination of host name, protocol and port number). For example, JavaScript
on a Web page from http://foo.com can’t make AJAX calls to http://bar.com (or to
http://www.foo.com, https://foo.com or http://foo.com:999, for that matter).

CORS relaxes this restriction by letting servers indicate which origins are allowed to call them.
CORS is enforced by browsers but must be implemented on the server, and the most recent
release of ASP.NET Web API 2 has full CORS support. With Web API 2, you can configure
policy to allow JavaScript clients from a different origin to access your APIs.

CORS Basics

To use the new CORS features in Web API, it’s helpful to understand the details of CORS itself,
because the Web API implementation is true to the specification. These details might seem
pedantic now, but they’ll be useful later to understand the available settings in Web API—and
when you’re debugging CORS they’ll help you fix problems faster.

The general mechanics of CORS are such that when JavaScript is attempting to make a
cross-origin AJAX call the browser will “ask” the server if this is allowed by sending headers in
the HTTP request (for example, Origin). The server indicates what’s allowed by returning HTTP
headers in the response (for example, Access-Control-Allow-Origin). This permission check is
done for each distinct URL the client invokes, which means different URLs can have different
permissions.

In addition to the origin, CORS lets a server indicate which HTTP methods are allowed, which
HTTP request headers a client can send, which HTTP response headers a client can read, and
if the browser is allowed to automatically send or receive credentials (cookies or authorization
headers). Additional request and response headers indicate which of these features are
allowed. These headers are summarized in Figure 1 (note that some of the features have no
header sent in the request—only the response).

Figure 1 CORS HTTP Headers

Permission/Feature Request Header Response Header


Origin Origin Access-Control-Allow-Origin
HTTP method Access-Control-Request-Method Access-Control-Allow-Method
Request headers Access-Control-Request-Headers Access-Control-Allow-Headers
Response headers Access-Control-Expose-Headers
Credentials Access-Control-Allow-Credentials
Cache preflight response Access-Control-Max-Age
Browsers can ask the server for these permissions in two different ways: simple CORS requests
and preflight CORS requests.

Simple CORS Requests Here’s an example of a simple CORS request:

POST http://localhost/WebApiCorsServer/Resources/ HTTP/1.1


Host: localhost
Accept: */*
Origin: http://localhost:55912
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
value1=foo&value2=5
And the response:

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Access-Control-Allow-Origin: http://localhost:55912
Content-Length: 27
{"Value1":"foo","Value2":5}
The request is a cross-origin request from http://localhost:55912 to http://localhost, and the
browser adds an Origin HTTP header in the request to indicate the calling origin to the server.
The server responds with an Access-​Control-Allow-Origin response header indicating that this
origin is allowed. The browser enforces the server’s policy, and the JavaScript will receive its
normal success callback.
The server can either respond with the exact origin value from the request or a value of “*”
indicating any origin is allowed. If the server hadn’t allowed the calling origin, then the
Access-Control-Allow-Origin header would simply be absent and the calling JavaScript’s error
callback would be invoked.

Note that with a simple CORS request the call on the server is still invoked. This can be
surprising if you’re still learning about CORS, but this behavior is no different from a scenario
where the browser had constructed a <form> element and made a normal POST request.
CORS doesn’t prevent the call from being invoked on the server; rather, it prevents the calling
JavaScript from receiving the results. If you want to prevent the caller from invoking the server,
then you’d implement some sort of authorization in your server code (possibly with the
[Authorize] authorization filter attribute).

The preceding example is known as a simple CORS request because the type of AJAX call
from the client was either a GET or a POST; the Content-Type was one of
application/x-www-form-​urlencoded, multipart/form-data, or text/plain; and there were no
additional request headers sent. If the AJAX call was another HTTP method, the Content-Type
was some other value or the client wanted to send additional request headers, then the request
would be considered a preflight request. The mechanics of preflight requests are slightly
different.

Preflight CORS Requests If an AJAX call isn’t a simple request, then it requires a preflight
CORS request, which is simply an additional HTTP request to the server to obtain permission.
This preflight request is made automatically by the browser and uses the OPTIONS HTTP
method. If the server responds successfully to the preflight request and grants permission, then
the browser will perform the actual AJAX call the JavaScript is attempting to make.

If performance is a concern (and when isn’t it?), then the outcome of this preflight request can
be cached by the browser by including the Access-Control-Max-Age header in the preflight
response. The value contains the number of seconds for which the permissions can be cached.

Here’s an example of a preflight CORS request:

OPTIONS http://localhost/WebApiCorsServer/Resources/1 HTTP/1.1


Host: localhost
Access-Control-Request-Method: PUT
Origin: http://localhost:55912
Access-Control-Request-Headers: content-type
Accept: */*
And the preflight response:

HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://localhost:55912
Access-Control-Allow-Methods: PUT
Access-Control-Allow-Headers: content-typeAccess-Control-Max-Age: 600
Here’s the actual AJAX request:

PUT http://localhost/WebApiCorsServer/Resources/1 HTTP/1.1


Host: localhost
Content-Length: 27
Accept: application/json, text/javascript, */*; q=0.01
Origin: http://localhost:55912
Content-Type: application/json
{"value1":"foo","value2":5}
And the AJAX response:

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Access-Control-Allow-Origin: http://localhost:55912
Content-Length: 27
{"Value1":"foo","Value2":5}
Notice in this example a preflight CORS request is triggered because the HTTP method is PUT
and the client needs to send the Content-Type header to indicate that the request contains
application/json. In the preflight request (in addition to Origin) the
Access-Control-Request-Method and Access-Control-Request-Headers request headers are
used to ask for permission for the type of HTTP method and the additional header the client
wishes to send.

The server granted permission (and set a preflight cache duration) and then the browser
allowed the actual AJAX call. If the server didn’t grant permission to any of the requested
features, then the corresponding response header would’ve been absent, the AJAX call
wouldn’t have been made and the JavaScript error callback would’ve been invoked instead.

The preceding HTTP requests and responses were made using Firefox. If you were to use
Internet Explorer, then you’d notice an additional Accept header being requested. If you were to
use Chrome, you’d see both Accept and Origin additionally requested. Interestingly, you won’t
see Accept or Origin in the Access-Control-​Allow-Headers, as the specification says they’re
implied and can be omitted (which Web API does). It’s a point of debate if Origin and Accept
actually need to be requested, but given how these browsers work today, your Web API CORS
policy will most likely need to include them. It’s unfortunate that browser vendors don’t seem to
be consistent in their reading of the specification.

Response Headers It’s easy to give a client permission to access response headers using the
Access-Control-Expose-Headers response header. Here’s an example of an HTTP response
that allows the calling JavaScript to access the custom response header “bar”:
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Access-Control-Allow-Origin: http://localhost:55912Access-Control-Expose-Headers: bar
bar: a bar value
Content-Length: 27
{"Value1":"foo","Value2":5}
The JavaScript client can simply use the XMLHttpRequest getResponseHeader function to read
the value. Here’s an example using jQuery:

$.ajax({
url: "http://localhost/WebApiCorsServer/Resources/1",
// other settings omitted
}).done(function (data, status, xhr) {
var bar = xhr.getResponseHeader("bar");
alert(bar);
});
Credentials and Authentication Possibly the most confusing aspect of CORS has to do with
credentials and authentication. Generally, authentication with Web APIs can be done either with
a cookie or with an Authorization header (there are other ways, but these two are the most
common). In normal browser activity, if one of these has been previously established, then the
browser will implicitly pass these values to the server on subsequent requests. With cross-origin
AJAX, though, this implicit passing of the values must be explicitly requested in JavaScript (via
the withCredentials flag on the XMLHttpRequest) and must be explicitly allowed in the server’s
CORS policy (via the Access-Control-Allow-Credentials response header).

Here’s an example of a JavaScript client setting the withCredentials flag with jQuery:

$.ajax({
url: "http://localhost/WebApiCorsServer/Resources/1",
xhrFields: {
withCredentials: true
}
// Other settings omitted
});
The withCredentials flag does two things: If the server issues a cookie, the browser can accept
it; if the browser has a cookie, it can send it to the server.

Here’s an example of the HTTP response allowing credentials:

HTTP/1.1 200 OK
Set-Cookie: foo=1379020091825
Access-Control-Allow-Origin: http://localhost:55912
Access-Control-Allow-Credentials: true
The Access-Control-Allow-Credentials response header does two things: If the response has a
cookie, the browser can accept it; and if the browser sent a cookie on the request, the
JavaScript client can receive the results of the call. In other words, if the client sets
withCredentials, then the client will only see a success callback in the JavaScript if the server (in
the response) allows credentials. If withCredentials was set and the server doesn’t allow
credentials, the client won’t get access to the results and the client error callback will be
invoked.

The same set of rules and behaviors apply if the Authorization header is used instead of cookies
(for example, when using Basic or Integrated Windows authentication). An interesting note
about using credentials and the Authorization header: The server doesn’t have to explicitly grant
the Authorization header in the Access-Control-Allow-Headers CORS response header.

Note that with the Access-Control-Allow-Credentials CORS response header, if the server
issues this header, then the wildcard value of “*” can’t be used for Access-Control-Allow-Origin.
Instead the CORS specification requires the explicit origin to be used. The Web API framework
handles all of this for you, but I mention it here because you might notice this behavior while
debugging.

There’s an interesting twist to this discussion of credentials and authentication. The description
up to this point has been for the scenario where the browser is implicitly sending credentials. It’s
possible for a JavaScript client to explicitly send credentials (again, typically via the
Authorization header). If this is the case, then none of the aforementioned rules or behaviors
related to credentials applies.

For this scenario, the client would explicitly set the Authorization header on the request and
wouldn’t need to set withCredentials on the XMLHttpRequest. This header would trigger a
preflight request and the server would need to allow the Authorization header with the
Access-Control-Allow-Headers CORS response header. Also, the server wouldn’t need to issue
the Access-Control-​Allow-Credentials CORS response header.

Here’s what that client code would look like to explicitly set the Authorization header:

$.ajax({
url: "http://localhost/WebApiCorsServer/Resources/1",
headers: {
"Authorization": "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3Mi..."
}
// Other settings omitted
});
Here’s the preflight request:
OPTIONS http://localhost/WebApiCorsServer/Resources/1 HTTP/1.1
Host: localhost
Access-Control-Request-Method: GET
Origin: http://localhost:55912
Access-Control-Request-Headers: authorization
Accept: */*
Here’s the preflight response:

HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: authorization
Explicitly setting a token value in the Authorization header is a safer approach to authentication
because you avoid the possibility of cross-site request forgery (CSRF) attacks. You can see this
approach in the new Single-Page Application (SPA) templates in Visual Studio 2013.

Now that you’ve seen the basics of CORS at the HTTP level, I’ll show you how to use the new
CORS framework to emit these headers from Web API.

CORS Support in Web API 2

The CORS support in Web API is a full framework for allowing an application to define the
permissions for CORS requests. The framework revolves around the concept of a policy that
lets you specify the CORS features to be allowed for any given request into the application.

First, in order to get the CORS framework, you must reference the CORS libraries from your
Web API application (they’re not referenced by default from any of the Web API templates in
Visual Studio 2013). The Web API CORS framework is available via NuGet as the
Microsoft.AspNet.WebApi.Cors package. If you’re not using NuGet, it’s also available as part of
Visual Studio 2013, and you’ll need to reference two assemblies: System.Web.Http.Cors.dll and
System.Web.Cors.dll (on my machine these are located in C:\Program Files (x86)\Microsoft
ASP.NET\ASP.NET Web Stack 5\Packages).

Next, to express the policy, Web API provides a custom attribute class called
EnableCorsAttribute. This class contains properties for the allowed origins, HTTP methods,
request headers, response headers and whether credentials are allowed (which model all of the
details of the CORS specification discussed earlier).

Finally, in order for the Web API CORS framework to process CORS requests and emit the
appropriate CORS response headers, it must look at every request into the application. Web
API has an extensibility point for such interception via message handlers. Appropriately, the
Web API CORS framework implements a message handler called CorsMessageHandler. For
CORS requests, it will consult the policy expressed in the attribute for the method being invoked
and emit the appropriate CORS response headers.
EnableCorsAttribute The EnableCorsAttribute class is how an application can express its CORS
policy. The EnableCorsAttribute class has an overloaded constructor that can accept either
three or four parameters. The parameters (in order) are:

List of origins allowed


List of request headers allowed
List of HTTP methods allowed
List of response headers allowed (optional)
There’s also a property for allowing credentials (Supports​Credentials) and another for specifying
the preflight cache duration value (PreflightMaxAge).

Figure 2 shows an example of applying the EnableCors attribute to individual methods on a


controller. The values being used for the various CORS policy settings should match the CORS
requests and responses that were shown in the prior examples.

Figure 2 Applying the EnableCors Attribute to Action Methods


public class ResourcesController : ApiController
{
[EnableCors("http://localhost:55912", // Origin
null, // Request headers
"GET", // HTTP methods
"bar", // Response headers
SupportsCredentials=true // Allow credentials
)]
public HttpResponseMessage Get(int id)
{
var resp = Request.CreateResponse(HttpStatusCode.NoContent);
resp.Headers.Add("bar", "a bar value");
return resp;
}
[EnableCors("http://localhost:55912", // Origin
"Accept, Origin, Content-Type", // Request headers
"PUT", // HTTP methods
PreflightMaxAge=600 // Preflight cache duration
)]
public HttpResponseMessage Put(Resource data)
{
return Request.CreateResponse(HttpStatusCode.OK, data);
}
[EnableCors("http://localhost:55912", // Origin
"Accept, Origin, Content-Type", // Request headers
"POST", // HTTP methods
PreflightMaxAge=600 // Preflight cache duration
)]
public HttpResponseMessage Post(Resource data)
{
return Request.CreateResponse(HttpStatusCode.OK, data);
}
}
Notice each of the constructor parameters is a string. Multiple values are indicated by specifying
a comma-separated list (as is specified for the allowed request headers in Figure 2). If you wish
to allow all origins, request headers or HTTP methods, you can use a “*” as the value (you must
still be explicit for response headers).

In addition to applying the EnableCors attribute at the method level, you can also apply it at the
class level or globally to the application. The level at which the attribute is applied configures
CORS for all requests at that level and below in your Web API code. So, for example, if applied
at the method level, the policy will only apply to requests for that action, whereas if applied at
the class level, the policy will be for all requests to that controller. Finally, if applied globally, the
policy will be for all requests.

Following is another example of applying the attribute at the class level. The settings used in
this example are quite permissive because the wildcard is used for the allowed origins, request
headers and HTTP methods:

[EnableCors("*", "*", "*")]


public class ResourcesController : ApiController
{
public HttpResponseMessage Put(Resource data)
{
return Request.CreateResponse(HttpStatusCode.OK, data);
}
public HttpResponseMessage Post(Resource data)
{
return Request.CreateResponse(HttpStatusCode.OK, data);
}
}
If there’s a policy at multiple locations, the “closest” attribute is used and the others are ignored
(so the precedence is method, then class, then global). If you’ve applied the policy at a higher
level but then wish to exclude a request at a lower level, you can use another attribute class
called DisableCorsAttribute. This attribute, in essence, is a policy with no permissions allowed.

If you have other methods on the controller where you don’t want to allow CORS, you can use
one of two options. First, you can be explicit in the HTTP method list, as shown in Figure 3. Or
you can leave the wildcard, but exclude the Delete method with the DisableCors attribute, as
shown in Figure 4.

Figure 3 Using Explicit Values for HTTP Methods


[EnableCors("*", "*", "PUT, POST")]
public class ResourcesController : ApiController
{
public HttpResponseMessage Put(Resource data)
{
return Request.CreateResponse(HttpStatusCode.OK, data);
}
public HttpResponseMessage Post(Resource data)
{
return Request.CreateResponse(HttpStatusCode.OK, data);
}
// CORS not allowed because DELETE is not in the method list above
public HttpResponseMessage Delete(int id)
{
return Request.CreateResponse(HttpStatusCode.NoContent);
}
}
Figure 4 Using the DisableCors Attribute
[EnableCors("*", "*", "*")]
public class ResourcesController : ApiController
{
public HttpResponseMessage Put(Resource data)
{
return Request.CreateResponse(HttpStatusCode.OK, data);
}
public HttpResponseMessage Post(Resource data)
{
return Request.CreateResponse(HttpStatusCode.OK, data);
}
// CORS not allowed because of the [DisableCors] attribute
[DisableCors]
public HttpResponseMessage Delete(int id)
{
return Request.CreateResponse(HttpStatusCode.NoContent);
}
}
CorsMessageHandler The CorsMessageHandler must be enabled for the CORS framework to
perform its job of intercepting requests to evaluate the CORS policy and emit the CORS
response headers. Enabling the message handler is typically done in the application’s Web API
configuration class by invoking the EnableCors extension method:

public static class WebApiConfig


{
public static void Register(HttpConfiguration config)
{
// Other configuration omitted
config.EnableCors();
}
}
If you wish to provide a global CORS policy, you can pass an instance of the
EnableCorsAttribute class as a parameter to the EnableCors method. For example, the
following code would configure a permissive CORS policy globally within the application:

public static class WebApiConfig


{
public static void Register(HttpConfiguration config)
{
// Other configuration omitted
config.EnableCors(new EnableCorsAttribute("*", "*", "*"));
}
}
As with any message handler, the CorsMessageHandler can alternatively be registered
per-route rather than globally.

So that’s it for the basic, “out of the box” CORS framework in ASP.NET Web API 2. One nice
thing about the framework is that it’s extensible for more dynamic scenarios, which I’ll look at
next.

Customizing Policy

It should be obvious from the earlier examples that the list of origins (if the wildcard isn’t being
used) is a static list compiled into the Web API code. While this might work during development
or for specific scenarios, it isn’t sufficient if the list of origins (or other permissions) needs to be
determined dynamically (say, from a database).

Fortunately, the CORS framework in Web API is extensible such that supporting a dynamic list
of origins is easy. In fact, the framework is so flexible that there are two general approaches for
customizing the generation of policy.

Custom CORS Policy Attribute One approach to enable a dynamic CORS policy is to develop a
custom attribute class that can generate the policy from some data source. This custom attribute
class can be used instead of the EnableCorsAttribute class provided by Web API. This
approach is simple and retains the fine-grained feel of being able to apply an attribute on
specific classes and methods (and not apply it on others), as needed.

To implement this approach, you simply build a custom attribute similar to the existing
EnableCorsAttribute class. The main focus is the ICorsPolicyProvider interface, which is
responsible for creating an instance of a CorsPolicy for any given request. Figure 5 contains an
example.

Figure 5 A Custom CORS Policy Attribute


[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method,
AllowMultiple = false)]
public class EnableCorsForPaidCustomersAttribute :
Attribute, ICorsPolicyProvider
{
public async Task<CorsPolicy> GetCorsPolicyAsync(
HttpRequestMessage request, CancellationToken cancellationToken)
{
var corsRequestContext = request.GetCorsRequestContext();
var originRequested = corsRequestContext.Origin;
if (await IsOriginFromAPaidCustomer(originRequested))
{
// Grant CORS request
var policy = new CorsPolicy
{
AllowAnyHeader = true,
AllowAnyMethod = true,
};
policy.Origins.Add(originRequested);
return policy;
}
else
{
// Reject CORS request
return null;
}
}
private async Task<bool> IsOriginFromAPaidCustomer(
string originRequested)
{
// Do database look up here to determine if origin should be allowed
return true;
}
}
The CorsPolicy class has all the properties to express the CORS permissions to grant. The
values used here are just an example, but presumably they could be populated dynamically
from a database query (or from any other source).

Custom Policy Provider Factory The second general approach to building a dynamic CORS
policy is to create a custom policy provider factory. This is the piece of the CORS framework
that obtains the policy provider for the current request. The default implementation from Web
API uses the custom attributes to discover the policy provider (as you saw earlier, the attribute
class itself was the policy provider). This is another pluggable piece of the CORS framework,
and you’d implement your own policy provider factory if you wanted to use an approach for
policy other than custom attributes.

The attribute-based approach described earlier provides an implicit association from a request
to a policy. A custom policy provider factory approach is different from the attribute approach
because it requires your implementation to provide the logic to match the incoming request to a
policy. This approach is more coarse-grained, as it’s essentially a centralized approach for
obtaining a CORS policy.

Figure 6 shows an example of what a custom policy provider factory might look like. The main
focus in this example is the implementation of the ICorsPolicyProviderFactory interface and its
GetCorsPolicyProvider method.

Figure 6 A Custom Policy Provider Factory


public class DynamicPolicyProviderFactory : ICorsPolicyProviderFactory
{
public ICorsPolicyProvider GetCorsPolicyProvider(
HttpRequestMessage request)
{
var route = request.GetRouteData();
var controller = (string)route.Values["controller"];
var corsRequestContext = request.GetCorsRequestContext();
var originRequested = corsRequestContext.Origin;
var policy = GetPolicyForControllerAndOrigin(
controller, originRequested);
return new CustomPolicyProvider(policy);
}
private CorsPolicy GetPolicyForControllerAndOrigin(
string controller, string originRequested)
{
// Do database lookup to determine if the controller is allowed for
// the origin and create CorsPolicy if it is (otherwise return null)
var policy = new CorsPolicy();
policy.Origins.Add(originRequested);
policy.Methods.Add("GET");
return policy;
}
}
public class CustomPolicyProvider : ICorsPolicyProvider
{
CorsPolicy policy;
public CustomPolicyProvider(CorsPolicy policy)
{
this.policy = policy;
}
public Task<CorsPolicy> GetCorsPolicyAsync(
HttpRequestMessage request, CancellationToken cancellationToken)
{
return Task.FromResult(this.policy);
}
}
The main difference in this approach is that it’s entirely up to the implementation to determine
the policy from the incoming request. In Figure 6, the controller and origin could be used to
query a database for the policy values. Again, this approach is the most flexible, but it potentially
requires more work to determine the policy from the request.

To use the custom policy provider factory, you must register it with Web API via the
SetCorsPolicyProviderFactory extension method in the Web API configuration:

public static class WebApiConfig


{
public static void Register(HttpConfiguration config)
{
// Other configuration omitted
config.EnableCors();
config.SetCorsPolicyProviderFactory(
new DynamicPolicyProviderFactory());
}
}

Community Contributions in Action

ASP.NET Web API is an open source framework and is part of a larger set of open source
frameworks collectively called the ASP.NET Web Stack, which also includes MVC, Web Pages
and others.
These frameworks are used to build the ASP.NET platform and are curated by the ASP.NET
team at Microsoft. As curator of an open source platform, the ASP.NET team welcomes
community contributions, and the cross-origin resource sharing (CORS) implementation in Web
API is one such contribution.

It was originally developed by Brock Allen as part of the thinktecture IdentityModel security
library (thinktecture.github.io).

Debugging CORS

A few techniques come to mind to debug CORS if (and when) your cross-origin AJAX calls
aren’t working.

Client Side One approach to debugging is to simply use your HTTP debugger of choice (for
example, Fiddler) and inspect all HTTP requests. Armed with the knowledge gleaned earlier
about the details of the CORS specification, you can usually sort out why a particular AJAX
request isn’t being granted permission by inspecting the CORS HTTP headers (or lack thereof).

Another approach is to use your browser’s F12 developer tools. The console window in modern
browsers provides a useful error message when an AJAX calls fails due to CORS.

Server Side The CORS framework itself provides detailed trace messages using the tracing
facilities of Web API. As long as an ITraceWriter is registered with Web API, the CORS
framework will emit messages with information about the policy provider selected, the policy
used, and the CORS HTTP headers emitted. For more information on Web API tracing, consult
the Web API documentation on MSDN.

A Highly Requested Feature

CORS has been a highly requested feature for some time now, and finally it’s built in to Web
API. This article focuses heavily on the details of CORS itself, but that knowledge is crucial in
implementing and debugging CORS. Armed with this knowledge, you should be able to easily
utilize the CORS support in Web API to allow cross-origin calls in your applications.

Brock Allen is a consultant specializing in the Microsoft .NET Framework, Web development
and Web-based security. He’s also an instructor for the training company DevelopMentor,
associate consultant for thinktecture GmbH & Co. KG, a contributor to thinktecture open source
projects and a contributor to the ASP.NET platform. You can reach him at his Web site,
brockallen.com, or e-mail him at brockallen@gmail.com.

Thanks to the following technical expert for reviewing this article: Yao Huan Lin (Microsoft)
Yao Huang Lin (yaohuang@microsoft.com) is a software developer on the ASP.NET Web API
team at Microsoft. He has worked on many components of the .NET Framework, including
ASP.NET, Windows Communication Foundation (WCF) and Windows Workflow Foundation
(WF).
----------------------

CORS on ASP.NET
If you don't have access to configure IIS, you can still add the header through ASP.NET by
adding the following line to your source pages:

Response.AppendHeader("Access-Control-Allow-Origin", "*");
Note: this approach is compatible with IIS6, IIS7 Classic Mode, and IIS7 Integrated Mode.

ASP.NET Web API


ASP.NET Web API 2 supports CORS.

To enable CORS support, add the Microsoft.AspNet.WebApi.Cors NuGet package to your


project.

Add this code to your configuration:

public static void Register(HttpConfiguration config)


{
// New code
config.EnableCors();
}
To enable cross-origin requests, add the [EnableCors] attribute to your Web API controller or
controller method:

[EnableCors(origins: "http://example.com", headers: "*", methods: "*")]


public class TestController : ApiController
{
// Controller methods not shown...
}
Enabling Globally
The method described above can also be used to enable CORS across the API without
annotating each controller:

public static void Register(HttpConfiguration config)


{
var corsAttr = new EnableCorsAttribute("http://example.com", "*", "*");
config.EnableCors(corsAttr);
}
--------------------
Enabling CORS in ASP.NET Web API 2

We recently completed an upgrade of one of our APIs to Web API 2. Previously we were using
a CORS implementation for Web API v1 by Brock Allen which later paved the way for the
support in Web API v2.

CORS can be enabled using a Web API specific package (which uses message handlers) or
OWIN Middleware. Which one to use will largely depend on your requirements:

When to use the Web API CORS package

You need fine grained control over CORS at the controller or action level (your API resources).
For example, you may wish to allow different origins/HTTP methods per resource.
You can find a tutorial covering how to configure the Web API CORS package here.

When to use the CORS OWIN middleware

You're using the OAuth middleware and need to authenticate client-side requests from another
domain (origin).
You want to enable CORS for all of your middleware components.
We decided to use the OWIN middleware. Detailed documentation is a little thin on the ground
with most examples just allowing all origins and HTTP methods:

app.UseCors(CorsOptions.AllowAll)
For finer grained control you can provide your own CorsPolicy:

public override void Register()


{
var corsPolicy = new CorsPolicy
{
AllowAnyMethod = true,
AllowAnyHeader = true
};

// Try and load allowed origins from web.config


// If none are specified we'll allow all origins

var origins = ConfigurationManager.AppSettings[Constants.CorsOriginsSettingKey];

if (origins != null)
{
foreach (var origin in origins.Split(';'))
{
corsPolicy.Origins.Add(origin);
}
}
else
{
corsPolicy.AllowAnyOrigin = true;
}

var corsOptions = new CorsOptions


{
PolicyProvider = new CorsPolicyProvider
{
PolicyResolver = context => Task.FromResult(corsPolicy)
}
};

app.UseCors(corsOptions);
}
The CorsOptions class has a PolicyProvider property which determines how the CorsPolicy for
the request will be resolved. This is how you could provide resource specific CORS policies but
it's not quite as nice to use as the attribute based Web API package.

Don't forget to allow OPTIONS

One thing that caught me out after enabling the middleware is that IIS was intercepting pre-flight
requests. To ensure ASP.NET handles OPTION requests, add the following in web.config:

<system.webServer>
<handlers>
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<remove name="OPTIONSVerbHandler" />
<remove name="TRACEVerbHandler" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*"
type="System.Web.Handlers.TransferRequestHandler"
preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
</system.webServer>
-------------------------------------------------------------------------------------------------------------

Create and consume web api using server side and ajax

Web API With AJAX: Understanding POST Request in Web API


By Sourav Kayal on Nov 30, 2013
This article provides a basic understanding of the Web API and concepts of AJAX in web
applications.
140.6k
5
2
facebook
twitter
linkedIn
google Plus
Reddit
expand
AngularJS JumpStart with Dan Wahlin
Web API with AJAX: Understand POST request in Web API

This is the first presentation of the "Web API with AJAX" article series. This article provides a
basic understanding of the Web API and concepts of AJAX in web applications. We can say that
the Web API is the latest communication technology of the Microsoft platform. If we look back at
Microsoft's communication technology we will find that communication started by holding the
hand of remoting techniques. Then the concept of Web Services was introduced that began the
use SOAP messages to send messages back and forth. It has a few limitations, such as only
being able to be consumed by HTTP and able to host on IIS. Then WCF took entry with useful
features. The limitation of IIS has gone and people started to host their application in various
environments. Then new problems began. It's a programmer's nightmare to configure endpoints
and consume them through a proper endpoint (If you are a good developer then you may ignore
the line that you have read just now) .Then Microsoft introduced the concept of the Web API in
MVC platforms on top of the traditional ASP.NET.

We can describe the Web API as a Swiss knife with many features and capabilities. It has
simplified the concept of communication. And supports true RESTful features. The most
beautiful advantage of the Web API is , it can be consumed by (almost) any type of client. It
does not matter whether your client is built using C# or JavaScript or by some other language
running on various platforms and devices. We will not continue our explanation much more
because this is not core to a Web API article. So, let's start our coding session by assuming that
you have a basic understanding of POST, GET , PUT and DELETE verbs of HTTP to talk about
Web API applications.

As per the title, we will understand how to consume the Web API service using a POST method.
If you are very new in this environment (read Web API and RESTful service) and still want to
read , then the following paragraph is for you.

When we talk about RESTful services we need to think of each and every object as being a
resource. Say for example we want to read the employee information whose id is 5, so the
information is nothing but a resource. If I want to get the picture of whose name is "flower" then I
think of the picture as nothing but a resource that can be consumed by a few HTTP verbs. In a
broad sense, consume implies save, retrieve, update and delete. Now, our beloved CRUD
operation can match with the HTTP verb. Here is the mapping sequence:

POST: Create
GET: Read
PUT: Update
DELETE: delete
So, the idea is that when we perform a create operation we well use the POST verb with respect
to the RESTful service and in this article we will use the jQuery ajax() function for the post
operation.
As per the concept of any service application, we need to implement both a client and a server.
Here we will implement the client using JavaScript and JQuey. So, let's start to write the code.

Implement client code to consume Web API

This is the client-side implementation to consume the Web API service. We are loading jQuery
from the local server and using the ajax() function.

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="APICall.aspx.cs"


Inherits="WebApplication1.APICall" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<script src="jquery-1.7.1.js" type="text/javascript"></script>
<script>
$(document).ready(function () {
$("#Save").click(function () {

var person = new Object();


person.name = $('#name').val();
person.surname = $('#surname').val();

$.ajax({
url: 'http://localhost:3413/api/person',
type: 'POST',
dataType: 'json',
data: person,
success: function (data, textStatus, xhr) {
console.log(data);
},
error: function (xhr, textStatus, errorThrown) {
console.log('Error in Operation');
}
});

});
});
</script>
</head>
<body>

<form id="form1">
Name :- <input type="text" name="name" id="name" />
Surname:- <input type="text" name="surname" id="surname" />
<input type="button" id="Save" value="Save Data" />
</form>
</body>
</html>

Please note the formation of the data that we are collecting from the HTML form. Since we have
configured the ajax() method to communicate with the JSON data, we need to form the data in
object format. So, this is the implementation of the client-side code.

Create Web API to serve RESTful service

In this section we will create the Web API application. We are skipping the basic Web API
creation part hoping you know that. Here is the implementation of Web API .

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;

namespace WebApplication1.WebAPI
{
public class person
{
public string name { get; set; }
public string surname { get; set; }
}

public class personController : ApiController


{
[HttpPost]
public string Post( person obj)
{
return obj.name + obj.surname;
}
}
}

At first we created a model class (person) that is very similar to the client object that we will
send from the client application. The person controller contains the Posr() method that is
specified with the HttpPost attribute. This implies that this action/method can be consumed by
the POST verb. We are halting the execution flow and checking the form data to the Web API.

Web-API1

In the Web API we are getting the value that we have sent from the client end.

Web-API2

In the successful callback function we are just printing this value to the console. Here is sample
output.

Web-API3

Use post() function of jQuery library

Here is another way to perform the POST operation. We can use the post() function to perform
the post operation. Basically the post() function is nothing but a shorthand implementation of the
ajax() function.

Have a look at the following code.

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="APICall.aspx.cs"


Inherits="WebApplication1.APICall" %>
<head runat="server">
<script src="jquery-1.7.1.js" type="text/javascript"></script>
<script>
$(document).ready(function () {
$("#Save").click(function () {
var person = new Object();
person.name = $('#name').val();
person.surname = $('#surname').val();

$.post('http://localhost:3413/api/person', person, function (data) {


console.log(data);
});
});
});
</script>
</head>
<body>

<form id="form1">
Name :- <input type="text" name="name" id="name" />
Surname:- <input type="text" name="surname" id="surname" />
<input type="button" id="Save" value="Save Data" />
</form>
</body>
</html>

Here is the output of the post() method.

Web-API4

Conclusion

This is the first lap of our Web API Ajax journey. Today we have learned the POST method and
the practical implementation of that. In a future article we will learn all types of HTTP verbs and
a few concepts of the Web API. Happy learning.
-----------------------------

Implementing & Consuming ASP.NET WEB API from JQuery (MVC 4)

PratapReddyP, 23 Jul 2012 CPOL

4.61 (28 votes)


Rate this:
vote 1vote 2vote 3vote 4vote 5
CodeProjectIn this post we will see how to create a our own WEB API service and will consume
it in client using JQuery.This is the UI i am planning to create, which in-turn talk to a ASP.NET
WEB API Service for rendering data.
In this post we will see how to create a our own WEB API service and will consume it in client
using JQuery.

This is the UI i am planning to create, which in-turn talk to a ASP.NET WEB API Service for
rendering data. We need to create a API Service and an Application consuming it.

Lets do it step by step.

Step 1: Create a solution and add 2 MVC 4 projects , one with WEB API template and another
with INTERNET Application template.

Step 2: Lets create our custom WEB API Service. Go to API_SVC project and under Controllers
folder you can see ValuesController.cs. This is the default WEB API service fie added, either
you can modify, or you can add a new API Controller, using Add option.

Step 3:I created a Service file with name "EmployeeAPI". EmployeeAPIConstroller.cs

Hide Shrink Copy Code


namespace API_SVC.Controllers
{
public class EmployeeAPIController : ApiController
{
private List<employee> EmpList = new List<employee>();
public EmployeeAPIController()
{
EmpList.Add(new Employee(1, "Employee1", "Employee Department1", 9999888877));
EmpList.Add(new Employee(2, "Employee2", "Employee Department2", 7777888899));
EmpList.Add(new Employee(3, "Employee3", "Employee Department3", 9999777788));
}
// GET api/EmployeeAPI
public IEnumerable<Employee> GetEmployees()
{
return EmpList;
}

// GET api/EmployeeAPI/5
public Employee GetEmployee(int id)
{
return EmpList.Find(e => e.ID == id);

// POST api/EmployeeAPI
public IEnumerable<Employee> Post(Employee value)
{
EmpList.Add(value);

return EmpList;
}

// PUT api/EmployeeAPI/5
public void Put(int id, string value)
{

// DELETE api/EmployeeAPI/5
public IEnumerable<Employee> Delete(int id)
{
EmpList.Remove(EmpList.Find(E => E.ID == id));
return EmpList;
}
}
}</employee>
Step 4:I ensure that it is hosted on IIS and can be accessed through URL mentioned on each of
the service methods. for example lets check GetEmployee() method using Fiddler.

Action:

Result:

Now that we confirm that we are done with creation of simple WEB API HTTP Service.

Step 5: Move to the second application i.e., API_APP , the MVC 4 internet application, and
open Index.cshtml under Home. To demonstrate the simplicity of ASP.NET WEB API Service, i
will call them using nothing but JQuery i.e., Client side code. Index.cshtml Code View:
Hide Shrink Copy Code
@{
ViewBag.Title = "Home Page";
}
@section featured {
<section class="featured">
<div class="content-wrapper">
<hgroup class="title">
<h1>@ViewBag.Title.</h1>
<h2>@ViewBag.Message</h2>
</hgroup>
<div>
<table><tr>
<td><button onclick="GetAllEmployees();return false;">Get All
Employees</button></td>
<td>Enter Employee Id: <input type="text" id="txtEmpid"
style="width:50PX"/></td>
<td><button onclick="GetEmployee();return false;">Get Employee</button></td>
<td>
<table>
<tr><td>EmpId:</td><td><input type="text" id="txtaddEmpid" /></td></tr>
<tr> <td>Emp Name:</td><td><input type="text" id="txtaddEmpName"
/></td></tr>
<tr> <td>Emp Department:</td><td><input type="text" id="txtaddEmpDep"
/></td></tr>
<tr><td>Mobile no:</td><td><input type="text" id="txtaddEmpMob"
/></td></tr>
</table>
</td>
<td><button onclick="AddEmployee();return false;">Add
Employee</button></td>
<td>Delete Employee <input type="text" id="txtdelEmpId"
style="width:50PX"/></td>
<td><button onclick="DeleteEmployee(); return false;">Delete
Employee</button></td>
</tr></table>

</div>
</div>
</section>
}
<h3>Oputput of action done through WEB API:</h3>
<ol class="round">
<li>
<div id="divResult"></div>

</li>
</ol>
Index.cshtml UI view

Step 6: Lets see how we can associate each button to an action of API Service. First look at
"Get All Employees" button and its onclick event in above code.Its is calling "GetAllEmployees()"
, a script function in-turn calling WEB API Service using JQuery.

Hide Copy Code


function GetAllEmployees() {
jQuery.support.cors = true;
$.ajax({
url: 'http://localhost:8080/API_SVC/api/EmployeeAPI',
type: 'GET',
dataType: 'json',
success: function (data) {
WriteResponse(data);
},
error: function (x, y, z) {
alert(x + '\n' + y + '\n' + z);
}
});
}
Spare sometime looking at above code snippet. See the URL part of Ajax Get request, that is all
we need to consume the WEB API Service we created earlier. Make sure you give all the
parameters properly so that it invoke right methods.

Step 7: WriteResponse() and ShowEmployee() are the 2 methods i created to display the
JSON result in a proper way. Below is the JQuery part associating each button to a method of
WEB API Service.

Hide Shrink Copy Code


<script type="text/javascript">
function GetAllEmployees() {
jQuery.support.cors = true;
$.ajax({
url: 'http://localhost:8080/API_SVC/api/EmployeeAPI',
type: 'GET',
dataType: 'json',
success: function (data) {
WriteResponse(data);
},
error: function (x, y, z) {
alert(x + '\n' + y + '\n' + z);
}
});
}

function AddEmployee() {
jQuery.support.cors = true;
var employee = {
ID: $('#txtaddEmpid').val(),
EmpName: $('#txtaddEmpName').val(),
EmpDepartment: $('#txtaddEmpDep').val(),
EmpMobile: $('#txtaddEmpMob').val()
};

$.ajax({
url: 'http://localhost:8080/API_SVC/api/EmployeeAPI',
type: 'POST',
data:JSON.stringify(employee),
contentType: "application/json;charset=utf-8",
success: function (data) {
WriteResponse(data);
},
error: function (x, y, z) {
alert(x + '\n' + y + '\n' + z);
}
});
}

function DeleteEmployee() {
jQuery.support.cors = true;
var id = $('#txtdelEmpId').val()

$.ajax({
url: 'http://localhost:8080/API_SVC/api/EmployeeAPI/'+id,
type: 'DELETE',
contentType: "application/json;charset=utf-8",
success: function (data) {
WriteResponse(data);
},
error: function (x, y, z) {
alert(x + '\n' + y + '\n' + z);
}
});
}

function WriteResponse(employees) {
var strResult = "<table><th>EmpID</th><th>Emp Name</th><th>Emp
Department</th><th>Mobile No</th>";
$.each(employees, function (index, employee) {
strResult += "<tr><td>" + employee.ID + "</td><td> " + employee.EmpName +
"</td><td>" + employee.EmpDepartment + "</td><td>" + employee.EmpMobile + "</td></tr>";
});
strResult += "</table>";
$("#divResult").html(strResult);
}

function ShowEmployee(employee) {
if (employee != null) {
var strResult = "<table><th>EmpID</th><th>Emp Name</th><th>Emp
Department</th><th>Mobile No</th>";
strResult += "<tr><td>" + employee.ID + "</td><td> " + employee.EmpName +
"</td><td>" + employee.EmpDepartment + "</td><td>" + employee.EmpMobile + "</td></tr>";
strResult += "</table>";
$("#divResult").html(strResult);
}
else {
$("#divResult").html("No Results To Display");
}
}

function GetEmployee() {
jQuery.support.cors = true;
var id = $('#txtEmpid').val();
$.ajax({
url: 'http://localhost:8080/API_SVC/api/EmployeeAPI/'+id,
type: 'GET',
dataType: 'json',
success: function (data) {
ShowEmployee(data);
},
error: function (x, y, z) {
alert(x + '\n' + y + '\n' + z);
}
});
}
</script>
Step 8: What else we left with except verifying the output.

Action 1:

Action 2:

Action 3:

Action 4:

Step 9: Apart from fact that it is simple to configure and create, we need to consider that its a
RESTful service which is light weight and will have incredible performance.

Look at the below snapshot of HttpWatch Log for Action #1, which was completed in 50 milli
seconds. I accept both applications are on same machine and solution, but the communication
never happened through dlls. The execution happened via IIS just like typical service call. Even
if you add the Network lag, we should say it is a good performance.
--------------

GET method to call Web-API using jQuery ajax


Sourav.Kayal
Posted by Sourav Kayal in ASP.NET MVC category on 11/26/2013 for Beginner level | Points:
250 | Views : 15936 red flag

Post Article | Search Articles | Articles Home


In this article, we will learn how to call Web-API service using jQuery AJAX method.
GET method to call Web-API using JQuery AJAX
In this article we will understand how to call Web-API using JQuery AJAX function. We know
that Web-API is new version of Microsoft’s service oriented application. It comes associated with
MVC-4 template. Web-API has built on top of MVC architecture, so we can think that it is sub
set of MVC architecture. It’s fully RESTful service which can consume by HTTP verb. If you are
not aware about HTTP verb then this small discussion is for you.
GET:- when we click one any link generally we make GET request to server. To get GET any
resource we have to make GET request.
POST:- When we want to POST data to server we have to make POST request.
PUT:- This request is needed when we want to make update operation to server.
DELETE:- We can perform delete operation when we want to delete any resource.
As we have now understood the basic idea about RESTful service now we will understand how
to make AJAX call with Web-API.

Create client application to AJAX call

In this example we will create JQuery ajax() function to call Web-API. We know that to make
AJAX call we have to include JQuery library and in this example we have loaded this library
from our local system. Here is code implementation of ajax() function.
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="JSON.aspx.cs"
Inherits="MvcApplication1.JSON" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<script src="Scripts/jquery-1.7.1.js"></script>

<script>
$(document).ready(function () {
$.ajax({
url: 'http://localhost:3002/api/values',
type: 'GET',
dataType: 'json',
success: function (data, textStatus, xhr) {
console.log(data);
},
error: function (xhr, textStatus, errorThrown) {
console.log('Error in Database');
}
});
});
</script>

</head>
<body>
<form id="form1" runat="server">
<div>
</div>
</form>
</body>
</html>
In URL parameter we have specified the actual URL of RESTful service and we are making
GET call to API. The data type is specified as “JSON” means when data will send from server, it
will send as JSON format. We have specified two callback functions into ajax method. The
success callback will get fire if the call completes successfully otherwise error function will get
execute.

Create Web-API in MVC

Now we will create Web-API in MVC project template. So, open one MVC-4 web application and
choose Web-API template from that. We will find that the few default dummy controllers are
present in application. In this example we have modified the Values controller and kept GET
method into it.

The GET method will return array of string in JSON format.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;

namespace MvcApplication1.Controllers
{
public class ValuesController : ApiController
{
// GET api/values
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}

}
}
Point to be noted in Web-API is that it serializes data automatically no explicit serialization is
needed to send data through HTTP response. Web-API returns message in JSON format so
that the return data is very less. But in case of SOAP based service there is lot of data overhead
in message.

Here is output of above example.

Conclusion:-

In this article we have learned to call Web-API using GET method. Hope you have understood
the concept of both ajax() function and Web-API. In coming article we will explore more about
Web-API and AJAX call.
-----------------------------
**Server Side:

Simple Client Side Consume ASP.NET Web API Server

Chinh Vo Wili, 26 Aug 2015 CPOL

4.38 (7 votes)
Rate this:
vote 1vote 2vote 3vote 4vote 5
Send HTTP GET requests, consume ASP.NET Web API server
Link project on GitHub
This tip helps you understand how to consume ASP.NET Web API from client side .NET.

Background
In some cases, you want to be using ASP.NET Web API endpoint with a client. For example,
you want HTTP to give you GET some data back or POST/PUT/DELETE data to server. In this
article, I use the HttpClient to communicate between endpoint and client side.

First, we create project ASP.NET WEB API, add NORTHWIND db, add Nuget Package
AutoMapper at ServerAPI, HttpClient, Newtonsoft.Json at client side project, Mvc.Routing and
other dependency.

Using the Code


The source code has 2 parts: ServerAPI project for WEB API, ClientSide for client side call web
API.

Host project ServerAPI on the IIS/IIS express.


Access to the API through link: http://localhost/ConsumingAPI/api/Products to test the result.

Implement API server source code in ServerAPI project, ProductsController.cs.

Hide Copy Code


// GET api/Products
[HttpGet]
[Route("api/Products")]
public HttpResponseMessage GetProducts()
{
Mapper.CreateMap<Product, ProductDTO>();
var tempData = db.Products.ToList();
var products = Mapper.Map<List<Product>, List<ProductDTO>>(tempData);
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK,
products);
return response;
}
From client side, call API and get data JSON/XML. After that, deserialize data to object
ProductDTO.

Hide Copy Code


public static List<ProductDTO> GetListProduct()
{
List<ProductDTO> result;
const string url = "http://localhost/ConsumingAPI/api/Products ";

using (var client = new System.Net.Http.HttpClient())


{
client.BaseAddress = new Uri(url);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add
(new
System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
var response = client.GetAsync(url).Result;
var data = response.Content.ReadAsStringAsync().Result;
result = JsonConvert.DeserializeObject<List<ProductDTO>>(data);
}
return result;
}
It is similar for POST/PUT/DELETE methods. Kindly search and download any missing Nuget or
dependency if building source code error.
Hide Shrink Copy Code
public static void InsertProduct()
{
const string url = "http://localhost/ConsumingAPI/api/Products";

var product = new ProductDTO


{
ProductID = 0,
ProductName = "Test ProductName",
SupplierID = 1,
CategoryID = 1,
QuantityPerUnit = "10",
UnitPrice = 1000,
UnitsInStock = 6,
UnitsOnOrder = 10,
ReorderLevel = 1
};

using (var client = new System.Net.Http.HttpClient())


{
client.BaseAddress = new Uri(url);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add
(new MediaTypeWithQualityHeaderValue("application/json"));
var json = Newtonsoft.Json.JsonConvert.SerializeObject(product);
HttpContent content = new StringContent(json);
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
var response = client.PostAsync(url, content).Result;
}
}
-----------------------

Using HttpClient to Consume ASP.NET Web API REST Services


So you installed the ASP.NET MVC 4 Beta and followed the Web API introduction over at the
ASP.NET website. Great! You now have a nice HTTP based API that plays nicely with jQuery
and other client side JavaScript libraries, and even other server-side technologies. But how
exactly do we
Perform server side consumption of that API in .NET?

UPDATE
I updated the post and the examples with the full code for making GET's, POST's, PUT's, and
DELETE's. I didn't have much time, so let me know if there are any mistakes/issues.

Let's say that you want to build an uber-flexible n-tier architecture for your next great app. One
option for decoupling your layers is to build them as web services. That way you not only
decouple the code relationships, but you decouple the platforms as well.

For example, if you build your BLL (Business Logic Layer) as a web service any platform can
interact with it. Your presentation layer can be a MVC site, a WPF app, a mobile app, or
anything else you can think up. The only requirement is that the front end be able to reach the
web service and correctly talk to it.

Where's the meta data???

How are we going to generate the proxy classes for this new web service??? I'm not going to lie
and say that your old friend the "Add Service Reference..." dialog is going to be able to help you
out here. Because this is a simple HTTP based API, no meta data gets generated about the API
itself (at least as far as I know, and at the time of writing this post).

While I love the "automagical" nature of the "Add Service Reference..." dialog, it always scared
me a little bit. It hid a lot of code and required an active instance of the web service to be up and
running somewhere (locally was fine). Now, we have complete control over the serialization and
deserialization of the data and can write more testable code (more on that later).

Show me the frickin' code!

Attached is a working sample solution that demonstrates my examples below.

First, create a new ASP.NET MVC 4 project and select the Web API template. I called mine
"WebApi":

After the solution loads let's make sure that our web service is in an accesible location. Open up
the project Properties > Web and then set the Specific Page to be "Values" and the Specific
Port to be 9000. We'll reference that port in our test consumer in a minute:

You can test out the default API by just hitting F5. The local web service URL
(http://localhost:9000/api/values) should open in your default browser and you should see some
XML (The styling may be different in your browser):
<string>value 1</string>
<string>value 2</string>
(Note: If you want to see the JSON, you can send an HTTP "Accept Header". The Web API will
see this and spit back your data serialized to JSON. Make sure you use this header when
making requests from jQuery. Check out the ASP.NET Web API Introduction for an example, or
use Fiddler.)

When you ran your project, a route defined in the Global.asax sent your request to the
ValuesController in the Controllers folder. In the ValuesController, the request matched the first
action via the HTTP request method verb and the parameters. To see this in action try going to
http://localhost:9000/api/values/5. Additionally, requests can be mapped by name too.

So far so good. Let's spice up the API a little bit and return our own custom type. Create a new
class library project within your solution. I called mine "WebApi.Dal". Rename the deafult
"class1.cs" to "MyDataClass.cs" and let Visual Studio auto update the references. Now add
some properties. Mine ended up like this:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace WebApi.Dal
{
public class MyDataClass
{
public string MyProperty1 { get; set; }
public bool MyProperty2 { get; set; }
public int MyProperty3 { get; set; }
public decimal MyProperty4 { get; set; }
}
}
Now let's switch back to the Web API project. Add a reference to your DAL project and replace
the first controller action with this one:

// ... usings, namespace and class/controller declarations.

// GET /api/values
public MyDataClass Get()
{
return new MyDataClass
{
MyProperty1 = "Property 1", // String
MyProperty2 = true, // Bool
MyProperty3 = 987654, // Integer
MyProperty4 = 100.87m // Decimal
};
}

// Rest of the class/controller definition...


Now run the solution again and you should see this:

<mydataclass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<myproperty1>Property 1</myproperty1>
<myproperty2>true</myproperty2>
<myproperty3>987654</myproperty3>
<myproperty4>100.87</myproperty4>
</mydataclass>
Great! Piece of cake! Now back to the problem at hand.

Consuming the Web API Service

Back in Visual Studio create a Console Application project. I called mine "WebApi.Tester". Add
a reference to the WebApi.Dal project, but you don't need to add one to the WebApi project.
Having access to the classes that were used to serialize the Web API data will allow us to
deserialize the data easily, and we don't need any "direct" relation to the web service itself, just
the data it provides.

In the Nuget Package Manager search for System.Net.Http and install the package that
matches that name (a bunch of other results show up, but get the one from Microsoft) and the
one that matches the name with "Formatter" on the end.

Then search for "json" and add the Json.NET package from Newtonsoft.

Then Add a Reference to System.Net.Http.Formatting and System.Json.

Now you should now have references to:

Newtonsoft.Json
System.Json
System.Net.Http
System.Net.Http.Formatting
System.Net.Http.WebRequest
WebApi.Dal
When we go to test this setup, we want both the WebApi MVC project to run, as well as the
WebApi.Tester Console app. To do that, open up the Solution Properties, check the radio
button that says "Multiple startup projects", and set WebApi and WebApi.Tester as startup
projects:

Now we are ready to write some code. Here is a base client class I whipped up that provides a
generic interface to the Web API service:

public class BaseClient


{
protected readonly string _endpoint;

public BaseClient(string endpoint)


{
_endpoint = endpoint;
}

public T Get()
{
using (var httpClient = new HttpClient())
{
T result = default(T);
Task responseTask = null;

httpClient.GetAsync(_endpoint).ContinueWith((requestTask) =>
{
responseTask = requestTask;
HttpResponseMessage response = requestTask.Result;

response.EnsureSuccessStatusCode();

response.Content.ReadAsAsync().ContinueWith((readTask) =>
{
result = readTask.Result;
});
});

// HACK: My version of the await keyword


while (responseTask == null || !responseTask.IsCompleted || result == null) { }

return result;
}
}
}
(Important: As of this writing, the above code may fail. Keep reading for a solution.)

So about that code above... it doesn't always work... It appears that there is some issue with
the deserializer and I get the following exception when reading the result from the inner async
method:

"The input stream contains too many delimiter characters which may be a sign that the incoming
data may be malicious."

Basically, there is some sort of "security" measure in place in case the data is too big and there
are too many delimiters.

Not to worry, I got your back! Just substitute that inner async call with this one, which delegates
the deserialization to the Newtonsoft JSON library!

response.Content.ReadAsStringAsync().ContinueWith((readTask) =>
{
result = JsonConvert.DeserializeObject(readTask.Result);
});
I asked about the above issue on the official ASP.NET forums and I got a response on this
thread. It looks like you just need to set the SkipStreamLimitChecks static property to true on
the MediaTypeFormatter class. As of this writing, I haven't tested that solution but I left the
commented samples intact in case you want to give it a go.

But let's be honest with eachother. You think that code is ugly. It is ugly, it's not just you. So I
started another thread about how to reign that code in and clean it up. I got a great response
from a guy in this thread. Since the async code is so ugly in .NET 4, and in my case it wasn't
really needed, I left it out. So the first return is the one that executes in the example and it's still
using Newtonsoft JSON:

public T Get()
{
using (var httpClient = new HttpClient())
{
var response = httpClient.GetAsync(_endpoint).Result;

// This works:
return JsonConvert.DeserializeObject(response.Content.ReadAsStringAsync().Result);

// This may not work:


return response.Content.ReadAsAsync().Result;

// This may not work:


return response.Content.ReadAsOrDefaultAsync().Result;
}
}
So now my code is a lot shorter, cleaner and easier to grok. For now we're basically skipping
the async stuff, but I think that's a smart decision until we can leverage the await keyword and
all it's compiler magic. For a quick sample of how the await keyword in .NET 4.5 relates to the
Web API, check out this post by the architect behind all this stuff, Henrik F Nielsen.

Sample Solution

I threw together a simple sample solution that is a complete working example. Nuget package
restore is enabled and I removed all the packages to make the zip file as small as possible. The
first build of the solution will take a minute because it has to go fetch all the packages and their
dependencies. Let me know if you have any problems running the code.

Web API with HttpClient Sample Solution

In case you don't feel like downloading the zip, the full relevant code from the solution is below:

using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Formatting;
using System.Net.Http.Headers;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;

public class BaseClient


{
protected readonly string _endpoint;

public BaseClient(string endpoint)


{
_endpoint = endpoint;
}

public T Get<t>(int top = 0, int skip = 0)


{
using (var httpClient = new HttpClient())
{
var endpoint = _endpoint + "?";
var parameters = new List<string>();

if (top > 0)
parameters.Add(string.Concat("$top=", top));

if (skip > 0)
parameters.Add(string.Concat("$skip=", skip));

endpoint += string.Join("&", parameters);

var response = httpClient.GetAsync(endpoint).Result;

return
JsonConvert.DeserializeObject<t>(response.Content.ReadAsStringAsync().Result);
}
}

public T Get<t>(int id)


{
using (var httpClient = NewHttpClient())
{
var response = httpClient.GetAsync(_endpoint + id).Result;

return
JsonConvert.DeserializeObject<t>(response.Content.ReadAsStringAsync().Result);
}
}

public string Post<t>(T data)


{
using (var httpClient = NewHttpClient())
{
var requestMessage = GetHttpRequestMessage<t>(data);

var result = httpClient.PostAsync(_endpoint, requestMessage.Content).Result;

return result.Content.ToString();
}
}

public string Put<t>(int id, T data)


{
using (var httpClient = NewHttpClient())
{
var requestMessage = GetHttpRequestMessage<t>(data);

var result = httpClient.PutAsync(_endpoint + id, requestMessage.Content).Result;

return result.Content.ReadAsStringAsync().Result;
}
}

public string Delete(int id)


{
using (var httpClient = NewHttpClient())
{
var result = httpClient.DeleteAsync(_endpoint + id).Result;

return result.Content.ToString();
}
}

protected HttpRequestMessage GetHttpRequestMessage<t>(T data)


{
var mediaType = new MediaTypeHeaderValue("application/json");
var jsonSerializerSettings = new JsonSerializerSettings();
jsonSerializerSettings.Converters.Add(new IsoDateTimeConverter());

var jsonFormatter = new JsonNetFormatter(jsonSerializerSettings);

var requestMessage = new HttpRequestMessage<t>(data, mediaType, new


MediaTypeFormatter[] { jsonFormatter });

return requestMessage;
}

protected HttpClient NewHttpClient()


{
return new HttpClient();
}
}
------------------------------------------------------------------------------------------------------

HTTP Status Messages


« PreviousNext Reference »
When a browser requests a service from a web server, an error might occur.
This is a list of HTTP status messages that might be returned:

1xx: Information
Message: Description:
100 Continue The server has received the request headers, and the client should proceed to
send the request body
101 Switching Protocols The requester has asked the server to switch protocols
103 Checkpoint Used in the resumable requests proposal to resume aborted PUT or
POST requests
2xx: Successful
Message: Description:
200 OK The request is OK (this is the standard response for successful HTTP requests)
201 Created The request has been fulfilled, and a new resource is created
202 Accepted The request has been accepted for processing, but the processing has not been
completed
203 Non-Authoritative Information The request has been successfully processed, but is
returning information that may be from another source
204 No Content The request has been successfully processed, but is not returning any
content
205 Reset Content The request has been successfully processed, but is not returning any
content, and requires that the requester reset the document view
206 Partial Content The server is delivering only part of the resource due to a range header
sent by the client
3xx: Redirection
Message: Description:
300 Multiple Choices A link list. The user can select a link and go to that location. Maximum five
addresses
301 Moved Permanently The requested page has moved to a new URL
302 Found The requested page has moved temporarily to a new URL
303 See OtherThe requested page can be found under a different URL
304 Not Modified Indicates the requested page has not been modified since last requested
306 Switch Proxy No longer used
307 Temporary Redirect The requested page has moved temporarily to a new URL
308 Resume Incomplete Used in the resumable requests proposal to resume aborted PUT
or POST requests
4xx: Client Error
Message: Description:
400 Bad Request The request cannot be fulfilled due to bad syntax
401 Unauthorized The request was a legal request, but the server is refusing to respond to
it. For use when authentication is possible but has failed or not yet been provided
402 Payment Required Reserved for future use
403 Forbidden The request was a legal request, but the server is refusing to respond to it
404 Not Found The requested page could not be found but may be available again in the
future
405 Method Not Allowed A request was made of a page using a request method not
supported by that page
406 Not Acceptable The server can only generate a response that is not accepted by the
client
407 Proxy Authentication Required The client must first authenticate itself with the proxy
408 Request Timeout The server timed out waiting for the request
409 Conflict The request could not be completed because of a conflict in the request
410 Gone The requested page is no longer available
411 Length Required The "Content-Length" is not defined. The server will not accept the
request without it
412 Precondition Failed The precondition given in the request evaluated to false by the
server
413 Request Entity Too Large The server will not accept the request, because the
request entity is too large
414 Request-URI Too Long The server will not accept the request, because the URL is too
long. Occurs when you convert a POST request to a GET request with a long query information
415 Unsupported Media Type The server will not accept the request, because the media
type is not supported
416 Requested Range Not Satisfiable The client has asked for a portion of the file, but the
server cannot supply that portion
417 Expectation Failed The server cannot meet the requirements of the Expect
request-header field
5xx: Server Error
Message: Description:
500 Internal Server Error A generic error message, given when no more specific message is
suitable
501 Not Implemented The server either does not recognize the request method, or it lacks the
ability to fulfill the request
502 Bad Gateway The server was acting as a gateway or proxy and received an invalid
response from the upstream server
503 Service Unavailable The server is currently unavailable (overloaded or down)
504 Gateway TimeoutThe server was acting as a gateway or proxy and did not receive a timely
response from the upstream server
505 HTTP Version Not Supported The server does not support the HTTP protocol version
used in the request
511 Network Authentication Required The client needs to authenticate to gain network
access
-------------------

Information responses EDIT


100 Continue
This interim response indicates that everything so far is OK and that the client should continue
with the request or ignore it if it is already finished.
101 Switching Protocol
This code is sent in response to an Upgrade: request header by the client, and indicates that the
protocol the server is switching too. It was introduced to allow migration to an incompatible
protocol version, and is not in common use.
Successful responsesEDIT
200 OK
The request has succeeded. The meaning of a success varies depending on the HTTP method:
GET: The resource has been fetched and is transmitted in the message body.
HEAD: The entity headers are in the message body.
POST: The resource describing the result of the action is transmitted in the message body.
TRACE: The message body contains the request message as received by the server
201 Created
The request has succeeded and a new resource has been created as a result of it. This is
typically the response sent after a PUT request.
202 Accepted
The request has been received but not yet acted upon. It is non-committal, meaning that there is
no way in HTTP to later send an asynchronous response indicating the outcome of processing
the request. It is intended for cases where another process or server handles the request, or for
batch processing.
203 Non-Authoritative Information
This response code means returned meta-information set is not exact set as available from the
origin server, but collected from a local or a third party copy. Except this condition, 200 OK
response should be preferred instead of this response.
204 No Content
There is no content to send for this request, but the headers may be useful. The user-agent may
update its cached headers for this resource with the new ones.
205 Reset Content
This response code is sent after accomplishing request to tell user agent reset document view
which sent this request.
206 Partial Content
This response code is used because of range header sent by the client to separate download
into multiple streams.
Redirection messagesEDIT
300 Multiple Choice
The request has more than one possible responses. User-agent or user should choose one of
them. There is no standardized way to choose one of the responses.
301 Moved Permanently
This response code means that URI of requested resource has been changed. Probably, new
URI would be given in the response.
302 Found
This response code means that URI of requested resource has been changed temporarily. New
changes in the URI might be made in the future. Therefore, this same URI should be used by
the client in future requests.
303 See Other
Server sent this response to directing client to get requested resource to another URI with an
GET request.
304 Not Modified
This is used for caching purposes. It is telling to client that response has not been modified. So,
client can continue to use same cached version of response.
305 Use Proxy
This means requested response must be accessed by a proxy. This response code is not
largely supported because security reasons.
306 unused
This response code is no longer used, it is just reserved currently. It was used in a previous
version of the HTTP 1.1 specification.
307 Temporary Redirect
Server sent this response to directing client to get requested resource to another URI with same
method that used prior request. This has the same semantic than the 302 Found HTTP
response code, with the exception that the user agent must not change the HTTP method used:
if a POST was used in the first request, a POST must be used in the second request.
308 Permanent Redirect
This means that the resource is now permanently located at another URI, specified by the
Location: HTTP Response header. This has the same semantics as the 301 Moved
Permanently HTTP response code, with the exception that the user agent must not change the
HTTP method used: if a POST was used in the first request, a POST must be used in the
second request.
Client error responsesEDIT
400 Bad Request
This response means that server could not understand the request due to invalid syntax.
401 Unauthorized
Authentication is needed to get requested response. This is similar to 403, but in this case,
authentication is possible.
402 Payment Required
This response code is reserved for future use. Initial aim for creating this code was using it for
digital payment systems however this is not used currently.
403 Forbidden
Client does not have access rights to the content so server is rejecting to give proper response.
404 Not Found
Server can not find requested resource. This response code probably is most famous one due
to its frequency to occur in web.
405 Method Not Allowed
The request method is known by the server but has been disabled and cannot be used. The two
mandatory methods, GET and HEAD, must never be disabled and should not return this error
code.
406 Not Acceptable
This response is sent when the web server, after performing server-driven content negotiation,
doesn't find any content following the criteria given by the user agent.
407 Proxy Authentication Required
This is similar to 401 but authentication is needed to be done by a proxy.
408 Request Timeout
This response is sent on an idle connection by some servers, even without any previous request
by the client. It means that the server would like to shut down this unused connection. This
response is used much more since some browsers, like Chrome or IE9, use HTTP
preconnection mechanisms to speed up surfing (see bug 881804, which tracks the future
implementation of such a mechanism in Firefox). Also note that some servers merely shut down
the connection without sending this message.
409 Conflict
This response would be sent when a request conflict with current state of server.
410 Gone
This response would be sent when requested content has been deleted from server.
411 Length Required
Server rejected the request because the Content-Length header field is not defined and the
server requires it.
412 Precondition Failed
The client has indicated preconditions in its headers which the server does not meet.
413 Payload Too Large
Request entity is larger than limits defined by server; the server might close the connection or
return an Retry-After header field.
414 URI Too Long
The URI requested by the client is longer than the server is willing to interpret.
415 Unsupported Media Type
The media format of the requested data is not supported by the server, so the server is rejecting
the request.
416 Requested Range Not Satisfiable
The range specified by the Range header field in the request can't be fulfilled; it's possible that
the range is outside the size of the target URI's data.
417 Expectation Failed
This response code means the expectation indicated by the Expect request header field can't be
met by the server.
421 Misdirected Request
The request was directed at a server that is not able to produce a response. This can be sent by
a server that is not configured to produce responses for the combination of scheme and
authority that are included in the request URI.
426 Upgrade Required
The server refuses to perform the request using the current protocol but might be willing to do
so after the client upgrades to a different protocol. The server MUST send an Upgrade header
field in a 426 response to indicate the required protocol(s) (Section 6.7 of [RFC7230]).
428 Precondition Required
The origin server requires the request to be conditional. Intended to prevent "the 'lost update'
problem, where a client GETs a resource's state, modifies it, and PUTs it back to the server,
when meanwhile a third party has modified the state on the server, leading to a conflict.
429 Too Many Requests
The user has sent too many requests in a given amount of time ("rate limiting").
431 Request Header Fields Too Large
The server is unwilling to process the request because its header fields are too large. The
request MAY be resubmitted after reducing the size of the request header fields.
451 Unavailable For Legal Reasons
The user requests an illegal resource, such as a web page censored by a government.
Server error responsesEDIT
500 Internal Server Error
The server has encountered a situation it doesn't know how to handle.
501 Not Implemented
The request method is not supported by the server and cannot be handled. The only methods
that servers are required to support (and therefore that must not return this code) are GET and
HEAD.
502 Bad Gateway
This error response means that the server, while working as a gateway to get a response
needed to handle the request, got an invalid response.
503 Service Unavailable
The server is not ready to handle the request. Common causes are a server that is down for
maintenance or that is overloaded. Note that together with this response, a user-friendly page
explaining the problem should be sent. This responses should be used for temporary conditions
and the Retry-After: HTTP header should, if possible, contain the estimated time before the
recovery of the service. The webmaster must also take care about the caching-related headers
that are sent along with this response, as these temporary condition responses should usually
not be cached.
504 Gateway Timeout
This error response is given when the server is acting as a gateway and cannot get a response
in time.
505 HTTP Version Not Supported
The HTTP version used in the request is not supported by the server.
506 Variant Also Negotiates
The server has an internal configuration error: transparent content negotiation for the request
results in a circular reference.
507 Variant Also Negotiates
The server has an internal configuration error: the chosen variant resource is configured to
engage in transparent content negotiation itself, and is therefore not a proper end point in the
negotiation process.
511 Network Authentication Required
The 511 status code indicates that the client needs to authenticate to gain network access.

S-ar putea să vă placă și