What is the Asp.Net Web API ?



Asp.Net WebAPI is the new web services framework released by Microsoft. As I already mentioned in one of my previous articles, it’s based on Asp.Net MVC with the core RESTful principles in mind. It’s basically an alternative to WCF which utilizes all the built-in HTTP functionalities, without the need of additional wrapping inside the body of the packet.



Why was the Web API created ?



To answer that question, we need to get back a few years.

In the near past, the Windows Communication Foundation (WCF) platform was the preferred way of building Microsoft service-oriented applications (and this is still the case in some situations). It was mature, with a lot of functionality, automatic remote proxy generation, et cetera. It was, of course, heavy; compared to some alternatives.

WCF is based on SOAP (Simple Object Access Protocol), which is basically XML, and use a special envelope to wrap the actual body along with any additional information. The built-in functionality of the transport protocol was not considered an option to carry any meta data.

This is considered one of its main drawbacks and one of the reasons the Web API was introduced. It utilizes the transport protocol functionality without any introduction of unnecessary abstractions.

Another reason is that there were already few other ways of creating REST-oriented services, including :

WCF with the WebHttp binding

The Asp.Net MVC service related features

Few open source frameworks

The WebHttp binding was a good attempt to introduce this paradigm into WCF, but soon it became clear that it’s nearly impossible to make this right with the core WCF in its heart.

On the other hand, the developers realized that Asp.Net MVC was actually good at serving content other than HTML. I used it myself in my last project to serve a browser API through JSON.

What’s the difference between the Web API and the MVC-based services ?



Asp.Net Web API is based on the MVC-introduced services. It has a lot their characteristics, including convention-over-configuration, model binding and validation, routing, filtering. These features, however, are not an exact match.

Asp.Net MVC fails on few general areas compared to Web API, including :

Dispatching actions according to verbs conventions

Content type negotiation based on information obtained through HTTP headers

Hosting outside of the Asp.Net stack and IIS (something that WCF can do without problem)

The Asp.Net Web API is simply an attempt to separate the service-oriented functionality out of MVC, and improve it.



Available HTTP methods

I’d like to point out few HTTP methods (also known as verbs), that are quite important when working with RESTful APIs.

The basic list of verbs is :

GET – used when requesting a resource from a web service

POST – used when the client is sending a bunch of information to the server, which is going to change the state of a resource

PUT – this verb is very much like POST, but it has a more specific function. A lot of people believe that it’s only used for updating a resource, but it can be used for creation also. POST is used for general information sending, like “I’m sending you this product or this form data, just write it down”. PUT, on the other hand, is used when you know the concrete resource you are targeting to create or update, with for example its unique identifier passed. If the resource exists, it will be modified.

DELETE – used to delete a resource from a web server

HEAD – used to retrieve information about the resource, but not the resource itself (meaning simple meta information)

TRACE – this method is used for debugging purposes, like receiving information about the path of the packet, any intermediate servers that might have changed the data, etc

OPTIONS – this method is used when the client wants more information about the end points available in the API

CONNECT – this method is usually used for establishing a connection while tunneling, for example in the case of – this method is usually used for establishing a connection while tunneling, for example in the case of SSH



This is the basic set of HTTP verbs defined in RFC 2616. I've found a complete list of methods added by WebDAV here.



The Web API controllers are async by design



The Asp.Net Web API controllers have a built-in support for asynchronous operations. That means that instead of working with one thread per request, it uses a dispatch thread to spawn additional one to work while serving other requests.

The reason is that there is a fixed amount of threads in the pool that the server can use. Although this can be changed through the application pool property, the number is still not infinite. In Asp.Net MVC you could use the AsyncController class to achieve the same effect.

Binding input parameters



In Asp.Net MVC, the input parameters passed to an action are usually being processed by the model binder, which parses any GET or POST request values. In Asp.Net Web API, the mechanism for handling parameters is slightly different. The input values are divided to “body values” and “non-body values”. Simple types that come from a query string are handled by the model binder. Body values, however, which come from POST requests, are being processed by the so called formatters.

There are three formatters built-in the Web API – one which decodes XML, one which decodes JSON, and one for any HTML form submission.



How is the actual data returned ?



In Asp.Net MVC, we had to return an object of type JsonResult and specify the outcome of the operation. In the case of Web API, we are no forced to do so. We can simply return a collection of something and the API will automatically decide which output format to use, based on the HTTP content-type parameter. But what will happen if there is an error ? Are we going to return null or something ? No, we’ll simply utilize the default error mechanism provided by .NET – we’ll throw an exception of type HttpResponceException.



Asp.Net Web API example



The following example illustrates the standard way of building a simple Web API service.

public class EmployeeController : ApiController { private DataContext context = new DataContext(); public IEnumerable<Employee> GetEmployees() { return context.Employees; } public Employee GetEmployee(int id) { Employee employee = context.Employees.Find(id); if (employee == null) { throw new HttpResponseException( Request.CreateResponse(HttpStatusCode.NotFound)); } return employee; } public HttpResponseMessage PutEmployee(int id, Employee employee) { if (id == employee.ID && ModelState.IsValid) { context.Entry(employee).State = EntityState.Modified; try { context.SaveChanges(); } catch (DbUpdateConcurrencyException) { return Request.CreateResponse(HttpStatusCode.NotFound); } return base.Request.CreateResponse(HttpStatusCode.OK, employee); } else { return Request.CreateResponse(HttpStatusCode.BadRequest); } } public HttpResponseMessage PostEmployee(Employee employee) { if (ModelState.IsValid) { context.Employees.Add(employee); context.SaveChanges(); HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created, employee); response.Headers.Location = new Uri(Url.Link("Employees", new { id = employee.ID })); return response; } else { return sRequest.CreateResponse(HttpStatusCode.BadRequest); } } public HttpResponseMessage DeleteEmployee(int id) { Employee employee = context.Employees.Find(id); if (employee == null) { return Request.CreateResponse(HttpStatusCode.NotFound); } context.Employees.Remove(employee); try { context.SaveChanges(); } catch (DbUpdateConcurrencyException) { return Request.CreateResponse(HttpStatusCode.NotFound); } return Request.CreateResponse(HttpStatusCode.OK, employee); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 public class EmployeeController : ApiController { private DataContext context = new DataContext ( ) ; public IEnumerable < Employee > GetEmployees ( ) { return context . Employees ; } public Employee GetEmployee ( int id ) { Employee employee = context . Employees . Find ( id ) ; if ( employee == null ) { throw new HttpResponseException ( Request . CreateResponse ( HttpStatusCode . NotFound ) ) ; } return employee ; } public HttpResponseMessage PutEmployee ( int id , Employee employee ) { if ( id == employee . ID && ModelState . IsValid ) { context . Entry ( employee ) . State = EntityState . Modified ; try { context . SaveChanges ( ) ; } catch ( DbUpdateConcurrencyException ) { return Request . CreateResponse ( HttpStatusCode . NotFound ) ; } return base . Request . CreateResponse ( HttpStatusCode . OK , employee ) ; } else { return Request . CreateResponse ( HttpStatusCode . BadRequest ) ; } } public HttpResponseMessage PostEmployee ( Employee employee ) { if ( ModelState . IsValid ) { context . Employees . Add ( employee ) ; context . SaveChanges ( ) ; HttpResponseMessage response = Request . CreateResponse ( HttpStatusCode . Created , employee ) ; response . Headers . Location = new Uri ( Url . Link ( "Employees" , new { id = employee . ID } ) ) ; return response ; } else { return sRequest . CreateResponse ( HttpStatusCode . BadRequest ) ; } } public HttpResponseMessage DeleteEmployee ( int id ) { Employee employee = context . Employees . Find ( id ) ; if ( employee == null ) { return Request . CreateResponse ( HttpStatusCode . NotFound ) ; } context . Employees . Remove ( employee ) ; try { context . SaveChanges ( ) ; } catch ( DbUpdateConcurrencyException ) { return Request . CreateResponse ( HttpStatusCode . NotFound ) ; } return Request . CreateResponse ( HttpStatusCode . OK , employee ) ; } }

The connection with the HTTP semantics is obvious. The action methods start with the verb in use, you are setting the proper HTTP response code, in the PostEmployee method you even set the location of the resource created.

The new Web API is a really good alternative to WCF. I'd even say that it complements it. I like the HTTP-oriented design, the direct access which is exposed for use. As most of us, I also like the control Asp.Net MVC provides us with, and it's the same with the Web API. I am still, however, not convinced that it should be used heavily for server-to-server communication. The REST APIs are great for client script applications, but they lack some of the heavy functionality WCF provides that is required in more complex scenarios.

Kosta Hristov ( 34 Posts Hi there ! My name is Kosta Hristov and I currently live in London, England. I've been working as a software engineer for the past 6 years on different mobile, desktop and web IT projects. I started this blog almost one year ago with the idea of helping developers from all around the world in their day to day programming tasks, sharing knowledge on various topics. If you find my articles interesting and you want to know more about me, feel free to contact me via the social links below. ;)

Like the article ? Share it ! ;)