Abstract
This article is based on learning concepts of ASP.NET Web API in order to create REST based API. In this article we will cover from basics to vast topics. So let’s get started with Day 1.
1 Introduction
As I am an ASP.NET developer I have been working in ASP.NET Web Forms, ASP.NET MVC, and Web Services etc. Today in this article I will try to demonstrate ASP.NET Web API into simpler terms that would indeed be easy to understand and implement them practically. If you love to watch and learn my honest suggestion would go and watch below series of Web API and be API Developer as well.
https://www.youtube.com/watch?v=cBpHqLukHp4
I won’t make any false assumptions for any technology. But as I have been working with Web Services and Web API. I can certainly found Web API to be much simpler, robust in all scenarios. Most of you would think why I am talking about Web Services when we have WCF. Yeah you are correct, as I don’t have in depth knowledge of WCF so I won’t comment on that. I would be happy if as a reader you dig into the open web and find the benefits of Web API over WCF as well. So let’s get started starting with definition of ASP.NET Web API.
“ASP.NET Web API is a HTTP services which follows HTTP REST protocols that can reach broad range of client’s i.e. Browser, mobile, tablets”
1.1 ASP.NET Web API
In short ASP.NET Web Api is a programming interface to define request and response message system. REST is a principle, way to use HTTP. HTTP Hyper Text Transfer Protocol was made of passing information from client to server and vice versa. ASP.NET Web API makes use of HTTP as their transfer protocol. ASP.NET Web API can be used to build or consume HTTP services as compared to SOAP. ASP.NET Web Api don’t force you to use HTTP principles which we are going to see in a while. ASP.NET Web Api takes advantage of HTTP like Media Type, HTTP message, Status Code, Content Negotiation, Caching etc. ASP.NET Web Api is an Open Source Project. These days Microsoft has been open sourcing there each and every new product, as a thought of that we can say that .net is moving towards below quote.
“NET –> May the Source be with you”
Figure 1: Source: https://twitter.com/markemalek
Scott Hanselman:
Principal Program Manager – Community Architect – Web Platform and Tools · Microsoft.
1.2 HTTP Protocol
HTTP is a text based protocol. You can read the specification from this URI https://www.w3.org/Protocols/rfc2616/rfc2616.html
HTTP request starts with a first line containing HTTP verbs (HTTP defined methods are called HTTP verbs) URL and HTTP Version. The HTTP header is a name-value field separated by a colon (:) and blank space called Payload.
POST http://localhost:51180/api/TodoItems HTTP/1.1 –HTTP Verbs content-type: application/json --Headers Host: localhost:51180 –Headers --Payload { Title:"Saillesh" }
HTTP Response starts with Status Code and its corresponding description and subsequently headers each line as shown below: The HTTP header is a name-value field separated by a colon (:) and blank space called Payload.
HTTP/1.1 201 Created Cache-Control: no-cache Pragma: no-cache Content-Type: application/json; charset=utf-8 Expires: -1 Location: http://localhost:51180/api/TodoItems/2 Server: Microsoft-IIS/10.0 --Payload {"TodoItemId":2,"Title":"Saillesh","IsDone":false}
1.3 ASP.NET WEB API Framework
Figure2: HTTP Web API mechanism
Figure3: ASP.NET WEB API can be used in variety of scenario.
1.3.1 HTTP Verbs
Before moving ahead towards coding let’s have a look over HTTP verbs. Http Verbs HTTP method that have been set in the HTTP specification.
GET :
GET Verb is used to get information about the resource. Resource is basically specified in the URI as shown below:
GET http://localhost:51180/api/TodoItems/2 HTTP/1.1 Host: localhost:51180
GET is the Verb followed by URI
HOST: Where the request is going with respect to domain
POST
POST Verb is used when we send data to save/created in the body section.
POST http://localhost:51180/api/TodoItems HTTP/1.1 Content-type: application/json Host: localhost:51180 { Title:"Saillesh" }
POST is the Verb followed by URI
HOST: Where the request is going with respect to domain
Content-Type: Type of content I am sending to the server i.e. application/json because I am sending json format.
Body: Body contains the Request format
PUT
PUT Verb is used when we want to update the resource information
Put http://localhost:51180/api/TodoItems HTTP/1.1
content-type: application/json
Host: localhost:51180
{ TodoItemId:3, Title:"Rahul" }
DELETE
DELETE Verb is used to delete resource from the server.
DELETE http://localhost:51180/api/TodoItems/3
content-type: application/json
Host: localhost:51180
1.3.2 HTTP STATUS CODE
As we are following REST Principle which uses HTTP, we have to be aware of HTTP Status Codes
- HTTP/1.1 200 OK – Specifies everything is ok the verb you performed has been successfully completed i.e. server found the resource
- 4o4 Server could not be found
- 503: Service Unavailable
Status codes are divided into 5 classes as show below:
- 1XX: Informational
- 2XX: Success i.e. Client request was successfully identified and accepted
- 200 OK GET
- 201 CREATED POST
- 3XX: Redirection i.e. client need further action in order to complete the request.
- 4XX: Client Error i.e. where client seems to have some wrong
- 401 Unauthorized
- 400 Bad Request
- 5XX: Server Problem
1.3.3 Content Negotiation
The word Content Negotiation means the client would send Accept Headers to the server that I understand these media type formatter i.e. (application/json, application/xml, application/bson etc). Please provide the response to be represented in this format. This part of HTTP Is referred as Content Negotiation or Conneg.
An Accept Header is initiated by the client. This header tell the server that the client is supporting these media types. The server gives back the response of its server driven content negotiation based on Conneg algorithm. When a client sends Accept Header to the server that tell the server the media type(s) the client want from the server.
Accept
- If a request is send to the server without any accept header and with a content type in headers. Than Conneg algorithm will choose Content type header to decide about Response media type to respond.
- If a request is send with an Accept Header, Conneg algorithm will use the Accept Header information to decide the Response media type to send the response.
- If client give us content type as application/json and accept-header: application/xml than conneg algorithm will use content type to serialize the input and accept header to decide the response media type formatter to write.
- If somehow conneg algo. Is not able to find the best fit media type formatter to be send in the Accept Header, than it’s uses the best effort approach and uses the content-type header to decide the response media type formatter to write.
- If in worst scenario if conneg algorithm is not able to find the correct response for the request, it uses the first media type formatter in collection i.e. application/json.
3. Implementing simple ASP.NET Web API Practically
To Demonstrate the ASP.NET Web API I will be using visual studio 2015. So let’s gets started.
Figure4:
Create New Project
Figure5:
Selecting Web API and Press Ok
Note* ASP.NET WEB API can be used within
- Web form Application
- MVC Application
- Console Application
- Windows
- WPF etc.
Figure6:
Project Loading Finished.
ASP.NET WEB API uses MVC architecture which means Model, View, and Controller. To learn about MVC architecture my honest suggestion for you is to watch the below video and clear your concepts of ASP.NET MVC.
https://www.youtube.com/watch?v=-c1sI8666Ac
In MVC our MODEL is our C# class, Controller is also an object which handles the client request and get the required model applies the logic with business class and send the data integrated with html to the client in the form of view.
Figure7:
Project Structure.
So let’s add our Model. In this Web Api we will performing CRUD Operations (Create, Read, Update, and Delete) operation on our Customer Model. We will be using Entity Framework which is an ORM tools which will communicate with our database schema. If you want to learn about Entity Framework my honest suggestion for you is to watch the below video and clear your concepts of Entity Framework.
https://www.youtube.com/watch?v=b6vTIiBNcJ0
Adding a Model
Figure8:
Adding a Model to your Project.
namespace WebApiDemo.Models { public class Customer { public int Id { get; set; } [Required,MaxLength(50)] //Name field is mandatory and max length is 50 public string Name { get; set; } [Required, MaxLength(10)] //Mobile field is mandatory and max length is 10 public string Mobile { get; set; } } }
Adding a Controller
Figure9:
Adding a Controller class to your Project
Figure10:
Selecting an Empty Controller
Figure11:
Naming the Controller with Model Name
Note* I won’t be implementing dependency injection and other design patterns. In Enterprise application our model, API, interface and dal has to be in separate class libraries.
Now let’s set up our DAL Class which will communicate with Database. I will be using EF code first approach with existing db table
Script for creating table: CREATE TABLE [dbo].[Customer]( [Id] [int] NOT NULL identity(1,1), [Name] [varchar](50) NOT NULL, [Mobile] [varchar](50) NOT NULL, CONSTRAINT [PK_Customer] PRIMARY KEY CLUSTERED ( [Id] AS )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY]
Figure13:
Table structure and columns and data types
Add DAL Class which will be responsible for talking with database table Customer.
Inherit the class from DbContext. DbContext gives the class all the setup that is needed to do the operation you want to do with DB Schema, or we can say it allows us to communicate with a DB.
namespace WebApiDemo.Models { //DbContext gives the class all the setup that is needed to do the operation //you want to perform with DB Schema, or we can say it allows us to communicate with a DB. public class DAL:DbContext { // DB Set maintains the DB connection with database public DbSet<Customer> customers { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { //mapping with the Customer Table modelBuilder.Entity<Customer>().ToTable("Customer"); } } }
Adding a Connection string Click on Server Explorer
Figure14:
Configuring the connection
Figure15:
Add Connection
Figure16:
Select your server name and enter your database name click ok.
Figure17: Demonstrating Right Click on Properties and go to Connection string
Figure18: Demonstrating connection string on Connection properties
<add
name=“DAL“
connectionString=“Data Source=DEVELOPER-VAIO;Initial Catalog=Demos;Integrated Security=True“
providerName=“System.Data.SqlClient“/>
Adding our first HTTP VERB into the controller
- POST
//used for help page to get the request and response type [ResponseType(typeof(Customer))] public HttpResponseMessage POST(Customer cust) { //if model validation gets fail return the Bad Request and return the model state if (!ModelState.IsValid) { return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState); } cust= _context.customers.Add(cust); _context.SaveChanges(); // data inserted successfully return the 201 created status and return the resource uri var response = Request.CreateResponse<Customer>(HttpStatusCode.Created, cust); response.Headers.Location = new Uri(Request.RequestUri, string.Format("customer/{0}", cust.Id)); return response; }
- GET All
public HttpResponseMessage Get() { //get the list of customers from tabl var customers = _context.customers.ToList(); //if customers is not null if (customers != null) { //return Customers with status 200 and response if (customers.Any()) return Request.CreateResponse(HttpStatusCode.OK, customers); } // return not found response return Request.CreateErrorResponse(HttpStatusCode.NotFound, "Customers not found"); }
- Get Single Customer
[ResponseType(typeof(Customer))] public HttpResponseMessage Get(int Id) { //get the list of customer from table var customer = _context.customers.Where(cust => cust.Id == Id).Single(); //if customer is not null if (customer!=null) {//return Customer with status 200 and response return Request.CreateResponse(HttpStatusCode.OK, customer); } // return not found response return Request.CreateResponse(HttpStatusCode.NotFound, "Customer not found"); }
4.PUT
public HttpResponseMessage Put(int id, [FromBody]Customer Cust) { if (!ModelState.IsValid) { return Request.CreateResponse(HttpStatusCode.BadRequest, ModelState); } if (id != Cust.Id) { return Request.CreateResponse(HttpStatusCode.BadRequest); } _context.Entry(Cust).State = EntityState.Modified; try { _context.SaveChanges(); } catch (DbUpdateConcurrencyException) { throw; } return Request.CreateResponse(HttpStatusCode.NoContent); }
- Delete
public HttpResponseMessage DeleteCustomer(int id) { //retrieve the customer first Customer customer = _context.customers.Find(id); //if customer object is null if (customer== null) { //return HttpStatusCode.NotFound response Request.CreateResponse(HttpStatusCode.NotFound, "No records found"); } //remove from the table _context.customers.Remove(customer); //save changes in database _context.SaveChanges(); //return response 200 return Request.CreateResponse(HttpStatusCode.OK); }
That’s it we have our working ASP.NET WebApi. Each Controller HTTP method has their corresponding URI. In ASP.NET Web API we use host/API/ControllerName which quiet differ from normal ASP.NET MVC routes. In ASP.NET Web API project we have WebApiConfig class for Web API routes
config.Routes.MapHttpRoute(
name: “DefaultApi”,
routeTemplate: “api/{controller}/{id}”,
defaults: new { id = RouteParameter.Optional }
We can see api/controller is the key here. Reason why using api in the routes is to avoid collision with ASP.NET MVC routing.
ControllerMethod |
URI |
POST | API/POST |
Get | API/GET |
Get(int Id) | API/GET/ID |
Put | API/GET/ID |
DeleteCustomer | API/DELETE/ID |
- Consuming Your Web API
In order to consume these API method we need a test client. We have various test clients softwares eg. Fiddler, POSTMAN, WebApiTest Package in Nuget, SOAP UI etc. I will be using google chrome extension POSTMAN for the same. Let get started.
If you don’t have POSTMAN my honest suggestion would be add the extension in your Google Chrom from below link.
https://chrome.google.com/webstore/detail/postman/fhbjgbiflinjbdggehcddcbncdddomop?hl=en
When you install the extension and Chrome App Launcher icon will created click on it and open POSTMAN or you can search for POSTMAN as shown below:
Figure19: Demonstrating searching POSTMAN via search.
Once you open the POSTMAN following window will open
Figure20: HomePage of POSTMAN REST client.
Figure21: Demonstrating BASIC terminology with POSTMAN.
Now In order to perform POST we will need to keep few points.
- Change HTTP verb from GET to POST.
- Define the Content type in header to tell the API that I am sending this media type.
- Define the Accept Header to tell the server I understand this media type more easily.
- Body: Sending JSON Body to be saved on the server.
POSTMAN Provide us autocomplete features by which we can easily enter the required details.
Figure22: Adding Content Type Header in POSTMAN.
Once we are done with headers our POSTMAN window will look like this as shown below:
Figure23: Configuring Headers and URI in POSTMAN.
Once we are done with headers now add your request body to be inserted to the DB. In order to add the request body click on body
Figure24: Configuring request Body.
Now click on Raw and enter your request in the json format, as we have written in headers that the content we are sending is of type application/json.
Figure25: Request body with properties names and value to be binded to object.
Wow we are ready fire our first HTTP verb POST just click on Send. Put a break point using f9 in your POST method.
POST:
Figure26: Break Point hits and we can see the passed json details are de-serialized to the customer object.
If the model state is valid it will perform the adding of the customer.
Figure27: Demonstrating Details being successfully stored in DB.
Once the details have been saved in DB HTTP StatusCode.Created is send to the client i.e. 201 and the location where the created resource present.
Figure28: Demonstrating Details being successfully stored in DB.
Now let’s GET the resource using the Location we received from POSTMAN. Add a new tab and insert all the details (Headers, verb). In GET method we not need to supply the body as we will pass id in query string.
http://localhost:56850/API/customer/1
Figure29: Demonstrating configuring GET verb in POSTMAN.
As we are done with configuring POSTMAN GET request hit send, the break point will get hit and the passed id will be binded to the Id variable.
GET:
Figure30: Step by Step Get Verb.
Once the whole statements are executed we will get below json response:
{ "Id": 1, "Name": "Saillesh", "Mobile": "1234567890" }
Headers:
Figure31: GET response.
PUT:
Figure32: Demonstrating configuring PUT verb in POSTMAN.
Now hit the send button.
Figure33: Step by Step PUT Verb.
Here I am updating old details of id 1 “Saillesh, 1234567890” to “Pawar,12345”.
Figure34: PUT Response
204 No Content
The server has recognized the request and has successfully processed but doesn’t need to return an entity body.
Let check the output in DB.
Figure35: Confirming records got updated.
DELETE:
Figure36 Step by Step DELETE Verb
Once the breakpoint is hit customer details will fetched and if it found then it will be deleted with success code 200. OK.
Figure37: Delete Response.
Acknowledgements
We found how easy it’s is to create REST based services using ASP.NET web API. Wow we have finally created a simple ASP.NET Web API give yourself high 5 from my side. There’s lot more to learn in ASP.NET web API stay tuned for more ASP.NET web API. The source code has been upload to Git Hub Repository. Feel free to download and test.
https://github.com/SailleshPawar/ASP.NET-WEB-API-DEMO/
References:
- http://www.asp.net/web-api
- Pro ASP.NET Web API by Tugberk Ugurlu (Author), Alexander Zeitler (Author), Ali Kheyrollahi (Author)
- https://www.w3.org/Protocols/Specs.html
- https://www.w3.org/Protocols/rfc2616/rfc2616.html