Introduction
In this article we will talk about the basics of ASP.NET Web API. We will try to understand what a Web API is, what is the basic structure of a Web API project. We will also create a simple application to demonstrate the CRUD operation on a simple entity using Web API.
Background
Connectivity between applications is a very important aspect from a business applications perspective. Nowadays there are a lot of mobile applications and single page applications are being created and such applications needs a strong service end that can provide these applications with the data and CRUD operations on the data.
SOAP and ASP.NET Web services
Traditionally, Web Services provided a great way of creating connected web applications. SOAP and XML created an excellent solution for creating connected web applications. SOAP is a standard XML based protocol that communicated over HTTP. We can think of SOAP as message format for sending messaged between applications using XML. It is independent of technology, platform and is extensible too. ASP.NET Web services provided an excellent way of creating SOAP based web services.
Note: Refer this article for details on Web Services: Understanding the Basics of Web Service in ASP.NET[^]
Problems with SOAP
The SOAP offered an excellent way of transferring the data between the applications. but the problem with SOAP was that along with data a lot of other meta data also needs to get transferred with each request and response. This extra information is needed to find out the capabilities of the service and other meta data related to the data that is being transferred coming from the server. This makes the payload heavy even for small data. Also, Web services needed the clients to create the proxy on their end. These proxies will do the marshaling and un-marshaling of SOAP WSDL and make the communication between the application and the web service possible. The problem with this proxy is that if the service is updated and the proxy on the
client is not then the application might behave incorrectly.
Welcome to REST
REST stands for Representational State Transfer. This is a protocol for exchanging data over a distributed environment. The main idea behind REST is that we should treat our distributed services as a resource and we should be able to use simple HTTP protocols to perform various operations on that resource.
When we talk about the Database as a resource we usually talk in terms of CRUD operations. i.e. Create, Retrieve, Update and Delete. Now the philosophy of REST is that for a remote resource all these operations should be possible and they should be possible using simple HTTP protocols.
Now the basic CRUD operations are mapped to the HTTP protocols in the following manner:
- GET: This maps to the R(Retrieve) part of the CRUD operation. This will be used to retrieve the required data (representation of data) from the remote resource.
- PUT: This maps to the U(Update) part of the CRUD operation. This protocol will update the current representation of the data on the remote server.
- POST: This maps to the C(Create) part of the CRUD operation. This will create a new entry for the current data that is being sent to the server.
- DELETE: This maps to the D(Delete) part of the CRUD operation. This will delete the specified data from the remote server.
so if we take an hypothetical example of a remote resource that contain a database of list of books. The list of books can be retrieved using a URL like:
www.testwebsite.com/books
To retrieve any specific book, lets say we have some ID that we can used to retrieve the book, the possible URL might look like:
www.testwebsite.com/books/1
Since these are GET requests, data can only be retrieved from the server. To perform other operations, if we use the similar URI structure with PUT, POST or DELETE operation, we should be able to create, update and delete the resource form the server. We will see how this can be done in implementation part.
Note: A lot more complicated queries can be performed using these URL structures. we will not be discussing the complete set of query operations that can be performed using various URL patterns.
Now the if we compare the REST API wit SOAP, we can see the benefits of REST. Firstly only the data will be traveling to and fro from the server because the capabilities of the service are mapped to the URIs and protocols. Secondly, there is no need to have a proxy at the client end because its only data that is coming and the application can directly receive and process the data.
WCF REST services
Windows Communication Foundation (WCF) came into existence much later than the web service. It provided a much secure and mature way of creating the services to achieve whatever we were not able to achieve using traditional web services, i.e., other protocols support and even duplex communication. With WCF, we can define our service once and then configure it in such a way that it can be used via HTTP, TCP, IPC, and even Message Queues. We can even configure WCF services to create REST services too i.e. WCF REST Services.
Note: Refer this article for details on WCF REST services: A Beginner's Tutorial for Understanding Windows Communication Foundation (WCF)[^]
The problem with using WCF restful services is that we need to do a lot of configurations in a WCF service to make it a RESTful service. WCF is suited for he scenarios where we want to create a services that should support special scenarios such as one way messaging, message queues, duplex communication or the services that need to conform to WS* specifications.
But using WCF for creating restful services that will provide fully resource oriented services over HTTP is a little complex. Still WCF is the only option for creating the RESTful services if there is a limitation of using .NET 3.5 framework.
Introducing ASP.NET Web API
Microsoft came up with ASP.NET Web API quite recently to facilitate the creation of RESTful services that are capable of providing fully resource oriented services for a broad range of clients including browsers, mobiles and tablets. ASP.NET Web API is a framework for building REST services easily and in a rather simple way.
Using the code
Let us start the discussion by creating a simple ASP.NET Web API project and looking at the project template. To create a Web API project we need to Create a new ASP.NET MVC 4.0 Web application.
After this we will be asked to select the project project template. Here we need to select the Web API template.
Once we have the Web API project template ready, we can see that the solution structure for the web api project is pretty similar to the structure of a MVC 4.0 website. But there are subtle differences and additions in some areas like routing, controllers and views.
Controllers: We get a ValuesController
which will contain the code to serve the HTTP requests. This controller is derived from an APIController
class and contains action methods for each HTTP action.
public class ValuesController : ApiController
{
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
public string Get(int id)
{
return "value";
}
public void Post([FromBody]string value)
{
}
public void Put(int id, [FromBody]string value)
{
}
public void Delete(int id)
{
}
}
Here each action method is associated with the HTTP method.
Routing: If we look in the App_Start folder we can find two route config files. One if RouteConfig.cs
which will contain the normal routes for the MVC 4.0 application. Other is the WebApiConfig.cs
which contains the routing for the WebAPI controllers.
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
The route template starts with the word api so as to distinguish the that the uri points to an API rather than a page. The controller will be mapped to the Controller class we have seen above.
The interesting part is that the route does not contain the information for action. The reason for this is that the action information will be coming as a part of HTTP method/action rather than in the uri and thus the uri does not need to know anything about the action here. The third parameter id is the value that will be passed to the action methods.
View: There are no views or the WebAPI controllers because these controllers will serve the raw data in either xml or json format(based on content negotiation) and they dont need any specific views to be associated with them.
A Note on Content Negotiation
Content negotiation means that the client and server will mutually agree on the format of the data that will be transfered between them. If the client wants the data in JSON or JSON format then it can specify this
in the header of the HTTP request and the server will serve the data in mentioned option. This option of either having XML format or JSON format returned can be specified as application/xml
and application/json
.
Lets Create a Sample Web API
Let us create a simple Web API that will implement all the basic CRUD operations on a sample database. Lets create a sample database with Books table. We will try to perform CRUD operations on this table.
To perform the Database operations within the service lets use Entity framework. This can very well be done by using ADO.NET calls or some other ORM but I chose entity framework. (please refer this to know about entity framework: An Introduction to Entity Framework for Absolute Beginners[^]). The generated Entity will look like following.
Let us now Create a BooksController
for handling and see how we can implement the actions in this controller for each HTTP method.
public class BooksController : ApiController
{
public IEnumerable<book> Get()
{
using (SampleDbEntities entities = new SampleDbEntities())
{
return entities.Books.ToList<book>();
}
}
public Book Get(int id)
{
using (SampleDbEntities entities = new SampleDbEntities())
{
return entities.Books.SingleOrDefault<book>(b => b.ID == id);
}
}
public HttpResponseMessage Post(Book value)
{
try
{
if (ModelState.IsValid)
{
using (SampleDbEntities entities = new SampleDbEntities())
{
entities.Books.AddObject(value);
entities.SaveChanges();
return Request.CreateResponse(HttpStatusCode.OK);
}
}
else
{
return Request.CreateResponse(HttpStatusCode.InternalServerError, "Invalid Model");
}
}
catch (Exception ex)
{
return Request.CreateResponse(HttpStatusCode.InternalServerError, ex.Message);
}
}
public HttpResponseMessage Put(int id, Book value)
{
try
{
using (SampleDbEntities entities = new SampleDbEntities())
{
Book foundBook = entities.Books.SingleOrDefault<book>(b => b.ID == id);
foundBook.BookName = value.BookName;
entities.SaveChanges();
return Request.CreateResponse(HttpStatusCode.OK);
}
}
catch (Exception ex)
{
return Request.CreateResponse(HttpStatusCode.InternalServerError, ex.Message);
}
}
public HttpResponseMessage Delete(int id)
{
try
{
using (SampleDbEntities entities = new SampleDbEntities())
{
Book foundBook = entities.Books.SingleOrDefault<book>(b => b.ID == id);
entities.Books.DeleteObject(foundBook);
entities.SaveChanges();
return Request.CreateResponse(HttpStatusCode.OK);
}
}
catch (Exception ex)
{
return Request.CreateResponse(HttpStatusCode.InternalServerError, ex.Message);
}
}
}
Now we have a simple web api ready to perform the CRUD operation on the Books database. Let us try to test these methods now. To test the get methods we simply need to use the URI in the browser and we can see the results.
Objective: Get a list of all books, URI: http://localhost:51377/api/Books, METHOD: HTTP GET
Objective: Get any specific book using id, URI: http://localhost:51377/api/Books/1, METHOD: HTTP GET
Objective: Add a new book, URI: http://localhost:51377/api/Books, METHOD: HTTP POST
To do this we can use postman and post the following data to the api.
<Book xmlns:i="http://www.w3.org/2001/XMLSchema-instance" z:Id="i1" xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/" xmlns="http://schemas.datacontract.org/2004/07/WebAPISample.Models">
<BookName>Yet Another Book</BookName>
</Book>
Objective: Update an existing book details,
URI: http://localhost:51377/api/Books/2,
METHOD: HTTP PUT
To do this we can use postman and PUT the following data to the api.
<Book xmlns:i="http://www.w3.org/2001/XMLSchema-instance" z:Id="i1" xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/" xmlns="http://schemas.datacontract.org/2004/07/WebAPISample.Models">
<BookName>Updated book</BookName>
</Book>
Objective: Delete an existing book,
URI: http://localhost:51377/api/Books/2,
METHOD: HTTP DELETE
To do this we can use postman and use DELETE method with the id passed on the URI to delete that book.
Note: The sample project also contains a nuget package called webapitestclient
. This can be used to test the Web API from the application itself by using http://localhost:51377/help. Also, the sample code contain nuget package dependencies but the actual packages are not included in the sample project so perhaps all the dependent packages should be downloaded before running the application
Point of interest
In this article we have discussed about the basics of ASP.NET Web API. We have also seen a sample implementation on how to implement a basic Web API to perform CRUD operations. This article has been written from a beginners perspective. I hope this has been informative.
History
- 26 September 2013: First version.