July 24, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

Introduction to ASP.NET Web API

  • April 19, 2012
  • By Bipin Joshi
  • Send Email »
  • More Articles »

Introduction

Developing software services, exposing them over a network and then consuming them in a variety of clients is not a new idea now. As far as .NET is concerned, Remoting, Web Services and WCF services allow us to develop a rich set of services. However, many modern internet based applications need to expose services over plain HTTP rather than making use of messaging formats such as SOAP. That is where ASP.NET Web API comes into the picture. Using ASP.NET Web API you can program for HTTP verbs such as GET, POST, PUT and DELETE. Once created, you can consume the Web API in a wide range of clients including web applications, desktop applications and mobile applications. This article is intended to give you a jump start in creating and consuming ASP.NET Web API. You will also learn to program CRUD operations that make use of Entity Framework and SQL Server over HTTP.

Software Required

In order to work through the examples presented in this article you will need ASP.NET MVC 4 and Json.NET. ASP.NET Web API is a part of ASP.NET MVC 4 Beta release and you can download it here. Additionally, you need to download Json.NET, a popular high-performance JSON framework for .NET. You will use Json.NET while developing a custom Web API formatter in later sections.

Creating ASP.NET MVC 4 Web API Application

The first step in creating ASP.NET Web API is to create a new project based on the Web API template. The following figure shows the relevant project template in Visual Studio.

Visual Studio Project Template
Visual Studio Project Template

Make sure to select "ASP.NET MVC 4 Web Application" and then select "Web API" project template.

Web API Project Template
Web API Project Template

The new project will have  folder structure quite similar to an MVC web application. However, there will be an additional controller - ValuesController - in the Controllers folder. The ValuesController is a Web API controller and inherits from the ApiController base class instead of Controller.

public class ValuesController : ApiController
{
...
}

The ValuesController class will also have empty skeleton methods for HTTP verbs viz. GET, POST, PUT and DELETE. The following table lists the mapping between various methods and HTTP verbs along with the purpose of each as far as our CRUD example is concerned.

Method

HTTP Verb

Description

Get()

GET

This method will return a set of application data in the form of a collection or array. Any IEnumerable collection type can be returned. Thus it represents SELECT operations returning multiple records.

Get(string)

GET

This method will typically return a single instance of data object based on the ID passed to it as a parameter. It represents SELECT operations returning a single row.

Post(string)

POST

Post does the job of adding a new data object in the system i.e. INSERT operations. The data to be added is passed as the parameter.

Put(string, string)

PUT

Put does the job of updating an existing data object in the system i.e. UPDATE operations. The ID of the existing data object is passed along with the modified version of the data.

Delete(string)

DELETE

This methods is intended to remove data objects from the system i.e. DELETE operations. It accepts ID of the data object to be removed as a parameter.

Note that our example uses Web API for performing a CRUD operation on a SQL Server database. However, Web API by itself doesn't mandate as to what processing should happen in each of these methods. You can, for example, deal with server side file system, XML data or a custom data store using these methods. Depending on your target operation and data store, the above methods will accept parameters of required data type.

Before you move any further, create a new folder named API under the application's root folder and move the ValuesController.cs file into it. Though doing so is not mandatory we will do it for the sake of separating Web API controllers from the normal MVC controllers.

Creating Entity Framework Data Model

Now, add a new Entity Framework data model in the Models folder. You will be using the Customers table of Northwind database to demonstrate CRUD operations. So, name the data model as Northwind.

Add a new Entity Framework data model in the Models folder
Add a new Entity Framework data model in the Models folder

While creating the data model choose the Customers table of Northwind database so as to create a data model as shown below:

Choose the Customers Table
Choose the Customers Table

Creating an API Controller

Next, you will fill in code in all of the Web API controller methods. The following code shows all of the Web API methods with the required code.

public class CustomersController : ApiController
{
    //Select All
    public IEnumerable<Customer> Get()
    {
        NorthwindEntities db = new NorthwindEntities();
        var data = from item in db.Customers
                   orderby item.CustomerID
                   select item;
        return data.ToList();
    }
 
 
    //Select By Id
    public Customer Get(string id)
    {
        NorthwindEntities db = new NorthwindEntities();
        var data = from item in db.Customers
                    where item.CustomerID == id
                    select item;
        return data.SingleOrDefault();
    }
 
    //Insert
    public void Post(Customer obj)
    {
        NorthwindEntities db = new NorthwindEntities();
        db.Customers.AddObject(obj);
        db.SaveChanges();
    }
 
 
    //Update
    public void Put(string id, Customer obj)
    {
        NorthwindEntities db = new NorthwindEntities();
        var data = from item in db.Customers
                    where item.CustomerID == id
                    select item;
        Customer old = data.SingleOrDefault();
        old.CompanyName = obj.CompanyName;
        old.ContactName = obj.ContactName;
        old.Country = obj.Country;
        db.SaveChanges();
    }
 
    //Delete
    public void Delete(string id)
    {
        NorthwindEntities db = new NorthwindEntities();
        var data = from item in db.Customers
                    where item.CustomerID == id
                    select item;
        Customer obj = data.SingleOrDefault();
        db.Customers.DeleteObject(obj);
        db.SaveChanges();
    }
}

The Get() method returns a List of Customer instances by fetching all of the records from the Customers table. The primary key column of the Customers table is CustomerID and is of string type. Hence, the other version of Get() method takes string id as a parameter and returns a Customer object depending on the CustomerID passed.

Post() method accepts a Customer object and then inserts the new Customer to the database. Similarly, the Put() method accepts a CustomerID that is to be updated and a Customer object with modified version of data. It then updates an existing customer with the modified data and saves the changes to the database. Finally, Delete() method accepts a CustomerID and deletes it from the database. The database operations inside these methods are fairly straightforward and we won't discuss them in detail here.

Calling the Web API from Browser

Before you consume the Customers Web API from a web page, let's test them in browser. Run the application and enter the following URL in the browser address bar.

Browser Address Bar
Browser Address Bar

Notice how the Web API is invoked - localhost<some_port>/api/customers. You will need to substitute the port number at your end. By default all Web API are accessed via /api/ root. This route is defined in Global.asax as follows:

public static void RegisterRoutes(RouteCollection routes)
{
    ...
    routes.MapHttpRoute(
        name: "DefaultApi",
        routeTemplate: "api/{controller}/{id}",
        defaults: new { id = RouteParameter.Optional }
    );
    ...
}

'Customers' is the name of the API controller class. If you wish to retrieve just a single Customer you will the CustomerID in the URL itself e.g.

/api/customers/ALFKI

Creating a Custom JSON Formatter

While testing the Web API in the browser the data is displayed in XML format. Web API framework automatically detects the requesting client and accordingly sends the response in a format that can be understood by the client. However, when you wish to consume it on some web page you will typically need the data in JSON format. JSON being the native format for JavaScript and JavaScript based libraries (such as jQuery) the serialization must happen in JSON format and that is where you will face a small issue.

As of this writing there is a known issue with Entity Framework entities and the default JSON formatter used by Web API. The entities of the EF data model have IsReference property of DataContractAttribute set to True.

...
[Serializable()]
[DataContractAttribute(IsReference=true)]
public partial class Customer : EntityObject
{
...
}

By default, Web API use DataContractJsonSerializer class for JSON serialization. The default JSON serializer can't handle serialization of such entities and at run time throws this exception:

The type 'WebAPIDemo.Models.Customer' cannot be serialized to JSON because its IsReference setting is 'True'. The JSON format does not support references because there is no standardized format for representing references. To enable serialization, disable the IsReference setting on the type or an appropriate parent class of the type.

To overcome the problem you need to create a custom JSON formatter. Luckily, there are third-party serializers available and you will use one of them - Json.NET. Though we won't go into too much detail of creating a custom formatter in this article, we will discuss the outline of the process. You can get the complete source code for the custom formatter class in the code download accompanying this article.

A custom formatter is basically a class that inherits from the MediaTypeFormatter base class. In our case the JsonNetFormatter makes use of Json.NET mentioned previously. So make sure that you have referenced the assembly of Json.NET before attempting to write the JsonNetFormatter code.

Reference the Assembly of Json.NET
Reference the Assembly of Json.NET

public class JsonNetFormatter : MediaTypeFormatter
{
...
}

You need to override certain methods of the MediaTypeFormatter base class as shown below.

protected override bool CanReadType(Type type)
{
...
}
 
protected override bool CanWriteType(Type type)
{
...
}
 
protected override Task<object> OnReadFromStreamAsync(Type type, Stream stream,
                                                      HttpContentHeaders contentHeaders,
                                                      FormatterContext formatterContext)
{
...
}
 
protected override Task OnWriteToStreamAsync(Type type, object value, Stream stream,
                                             HttpContentHeaders contentHeaders,
                                             FormatterContext formatterContext,
                                             TransportContext transportContext)
{
...
}

Once created you need to tell ASP.NET Web API framework to use the new formatter class instead of the default one. You do that in Global.asax file as shown below:

protected void Application_Start()
{
    HttpConfiguration config = GlobalConfiguration.Configuration;
    JsonSerializerSettings settings = new JsonSerializerSettings();
    settings.Converters.Add(new IsoDateTimeConverter());
    JsonNetFormatter formatter = new WebAPIDemo.Http.Formatters.JsonNetFormatter(settings);
    config.Formatters.Insert(0, formatter);
 
    AreaRegistration.RegisterAllAreas();
    RegisterGlobalFilters(GlobalFilters.Filters);
    RegisterRoutes(RouteTable.Routes);
    BundleTable.Bundles.RegisterTemplateBundles();
}

Notice the lines marked in bold letters. Here, you are creating an instance of the custom JSON formatter class and adding it to the Formatters collection of HttpConfiguration class.

Once you have registered the custom JSON formatter class you are ready to consume the Web API from any web page using client side script.

Consuming Web API from jQuery

You will consume Customers Web API from the Index View of the application. So, add a view for the Index() action method of the HomeController.

Add a View
Add a View

The Index view will display Customer data in an HTML table. You can then add, modify or delete customers. Though the Customers table contains many columns you will use just four of them viz. CustomerID, CompanyName, ContactName and Country. The following figure shows the Index view at runtime.

The Index View at Runtime
The Index View at Runtime

When the page loads in the browser the Get() Web API method is called to display customer data. Similarly, when you click on Insert, Update or Delete buttons Post(), Put() and Delete() Web API methods are called via jQuery code.

Now, let's add the jQuery code that calls the Web API.

Begin by adding an HTML table for displaying Customer data.

<table id="customerTable" border="0" cellpadding="3">
    <tr>
        <th>Customer ID</th>
        <th>Company Name</th>
        <th>Contact Name</th>
        <th>Country</th>
        <th>Actions</th>
    </tr>
    <tr>
        <td><input type="text" id="txtCustomerId" size="5"/></td>
        <td><input type="text" id="txtCompanyName" /></td>
        <td><input type="text" id="txtContactName" /></td>
        <td><input type="text" id="txtCountry" /></td>
        <td><input type="button" name="btnInsert" value="Insert" /></td>
    </tr>
</table>

As you can see the textboxes in the first row allow you to insert a new Customer. The remaining rows of the table will be added dynamically using jQuery since they depend on the data being fetched from the server.

Next, include a <script> reference to the jQuery library as shown below:

<script src="../../Scripts/jquery-1.6.2.min.js" type="text/javascript"></script>

In the ready() event handler you will call the Get() Web API method and fill the HTML table with existing customer data. This is done as follows:

$(document).ready(function () {
    $.getJSON("api/customers", LoadCustomers);
});

The ready() event handler makes use of getJSON() method of jQuery. As you might have guessed, the getJSON() method makes a GET request to a specified resource. The first parameter of getJSON() method is the URL of the Web API to be invoked and the second parameter is a function that will be called after data is received successfully. The LoadCustomers() function looks like this:

function LoadCustomers(data) {
    $("#customerTable").find("tr:gt(1)").remove();
    $.each(data, function (key, val) {
        var tableRow = '<tr>' + 
                        '<td>' + val.CustomerID + '</td>' +
                        '<td><input type="text" value="' + val.CompanyName + '"/></td>' +
                        '<td><input type="text" value="' + val.ContactName + '"/></td>' +
                        '<td><input type="text" value="' + val.Country + '"/></td>' +
                        '<td><input type="button" name="btnUpdate" value="Update" /> 
                             <input type="button" name="btnDelete" value="Delete" /></td>' + 
                        '</tr>';
        $('#customerTable').append(tableRow);
    });
 
    $("input[name='btnInsert']").click(OnInsert);
    $("input[name='btnUpdate']").click(OnUpdate);
    $("input[name='btnDelete']").click(OnDelete);
}

The LoadCustomers() function receives the data as a parameter. Firstly, you remove all the rows from the table except header and insert row. This is because you will be calling LoadCustomers() method multiple times and you wish to ensure that duplicate rows are not being added to the table. The function then iterates through the received set of data (array of Customer objects in our case) and with each iteration a new row is added to the table. The click event handlers of Insert, Update and Delete buttons are also wired to OnInsert, OnUpdate and OnDelete functions.

OnInsert, OnUpdate and OnDelete functions call Put(), Post() and Delete() Web API methods respectively. All of them make use of $.ajax() of jQuery. The OnUpdate() function is discussed in detail next.

function OnUpdate(evt) {
    var cell;
    var customerId = $(this).parent().parent().children().get(0).innerHTML;
    cell = $(this).parent().parent().children().get(1);
    var companyName = $(cell).find('input').val();
    cell = $(this).parent().parent().children().get(2);
    var contactName = $(cell).find('input').val();
    cell = $(this).parent().parent().children().get(3);
    var country = $(cell).find('input').val();
 
    var data = '{"id":"' + customerId + '", "obj":{"CustomerID":"' + customerId + 
               '","CompanyName":"' + companyName + '","ContactName":"' + 
               contactName + '","Country":"' + country + '"}}';
 
    $.ajax({
        type: 'PUT',
        url: '/api/customers/',
        data: data,
        contentType: "application/json; charset=utf-8",
        dataType: 'json',
        success: function (results) {
            $.getJSON("api/customers", LoadCustomers);
            alert('Customer Updated !');
        }
    })
}

Firstly, the OnUpdate() function retrieves modified data from various textboxes. It then creates a JSON representation of the CustomerID and Customer object. Recollect that Put() method accepts two parameters viz. id and obj. These parameters are passed in JSON format as shown above.

Have a look at the $.ajax() call carefully. The type parameter specifies the type of HTTP request and you specify it as PUT. The url parameter points to /api/customers/. The data parameter specifies method parameters in JSON format. Upon successful execution of the Put() method you simply repopulate the HTML table using $.getJSON() and LoadCustomers().

The OnInsert() and OnDelete() functions are similar to the OnUpdate() function and are shown next:

function OnInsert(evt) {
    var customerId = $("#txtCustomerId").val();
    var companyName = $("#txtCompanyName").val();
    var contactName = $("#txtContactName").val();
    var country = $("#txtCountry").val();
    var data = '{"obj":{"CustomerID":"' + customerId + '","CompanyName":"' + companyName + 
               '","ContactName":"' + contactName + '","Country":"' + country + '"}}';
 
    $.ajax({
        type: 'POST',
        url: '/api/customers/',
        data: data,
        contentType: "application/json; charset=utf-8",
        dataType: 'json',
        success: function (results) {
            $("#txtCustomerId").val('');
            $("#txtCompanyName").val('');
            $("#txtContactName").val('');
            $("#txtCountry").val('');
            $.getJSON("api/customers", LoadCustomers);
            alert('Customer Added !');
        }
    })
 
}
function OnDelete(evt) {
    var customerId = $(this).parent().parent().children().get(0).innerHTML;
    var data = '{"id":"' + customerId + '"}';
    var row = $(this).parent().parent();
 
    $.ajax({
        type: 'DELETE',
        url: '/api/customers/',
        data: data,
        contentType: "application/json; charset=utf-8",
        dataType: 'json',
        success: function (results) {
            $.getJSON("api/customers", LoadCustomers);
            alert('Customer Deleted!');
        }
    })
 
}

Notice that in all of the above jQuery code you never specified explicitly which method of the CustomersController should be invoked (Get(), Post(), Put(), Delete() etc.). Everywhere your URL is the same i.e. /api/customers. Depending on the HTTP verb you specify while making the request (GET, PUT, POST or DELETE), ASP.NET Web API automatically invokes the appropriate server side method.

In our example we used the default method names - Get(), Put(), Post() and Delete() - in the Web API. However, you can use any method names of the form GetXXXX(), PutXXXX(), PostXXXX() and DeleteXXXX() where XXXX is the name of your choice. ASP.NET Web API will still invoke the methods appropriately based on the method prefixes and signatures.

Now run the Index view and try Insert, Update and Delete operations. The following figure shows a Customer record being added to the table.

Customer Record Added
Customer Record Added

Calling Web API from Web Forms Application

Though ASP.NET Web APIs are part of ASP.NET MVC, they are not restricted just to MVC. You can also consume them in a Web Forms application. This section shows you how.

Add a new ASP.NET Web Forms application in the same solution. Then copy the API folder from the MVC application to the Web Forms application. As an alternative you can also add an ApiController class directly to the web forms project and then code the Web API methods as before.

Add an ApiController Class
Add an ApiController Class

Also, add the Entity Framework data model for Customers table as before. Open the Global.asax file of the Web Forms application and write the following code in it:

protected void Application_Start(object sender, EventArgs e)
{
    HttpConfiguration config = GlobalConfiguration.Configuration;
    JsonSerializerSettings settings = new JsonSerializerSettings();
    settings.Converters.Add(new IsoDateTimeConverter());
    JsonNetFormatter formatter = new WebAPIWebFormDemo.Http.Formatters.JsonNetFormatter(settings);
    config.Formatters.Insert(0, formatter);
 
    RouteTable.Routes.MapHttpRoute(
        name: "DefaultApi",
        routeTemplate: "api/{controller}/{id}",
        defaults: new { id = System.Web.Http.RouteParameter.Optional }
 
    );
}

This code should be familiar to you as you wrote it earlier for MVC application. The above code does two things. First, it registers your custom JSON formatter with the Web API framework. Second, it maps a route for Web API controllers.

Finally, copy/paste the same HTML and jQuery code from the Index view to the Index.aspx (or Default.aspx).

That's it! You can run the web form and see Web API in action in web forms application too.

Run the Web Form
Run the Web Form

Useful Resources

ScottGu's Blog - ASP.NET Web API (Part 1)

Henrik's Blog - Using JSON.NET with ASP.NET Web API

Thinktecture.Web.Http

Summary

ASP.NET Web API provides a simplified way of creating HTTP based services. Using Web API you can program GET, POST, PUT and DELETE verbs and expose server-side functionality to client applications. Though Web API is introduced as a part of MVC 4, they can also be used in Web Forms applications. A Web API essentially takes the form of a class inherited from the ApiController base class. You then need to write Get(), Post(), Put() and Delete() methods to program for the respective HTTP verb. The Web API thus developed can be consumed on a web page using client script. This article showed how Web API can be used for CRUD operations involving Entity Framework entities and SQL Server database.

Download the code for this article.


Tags: ASP.NET, JSON, Web API, HTTP




Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel