Mar
4
2012

CRUD operation using Web API in Asp.net Web form application

Introduction

There is lot of buzz going on around the word Web API these days. In this short article, we will look at the basic CRUD (Create, Read, Update, Delete) operations using Web API... but, In Web form application.

Background

The Web API is introduced as part of MVC 4 Beta. That dosen't mean we cannot take its advantage in web form applications (Non MVC). Before looking at implementation details, let's first see what is Web API and why it is important.

Little details of Web API

As an old Asp.net developer, you might have spend lot of time around Web services which is used to expose different services using SOAP contracts. Web API provides RESTful approach for exposing the similar services. The REST (REpresentational State Transfer) broadens the scope of usability of these services and most importantly, make it very easy for us (developers) to create and use them.

With Web API, we can simply access the certain resource/data by calling on a URL; similar to this.

http://www.SiteName.com/API/Record/ID

Web API class will then serve the request and can return the data in different formats. Mostly we would use XML or JSON data (there are other types supported though). In this article, I will use JSON to demonstrate use of Web API.

Article Body

I am going to explain implementation details of Web API in this article and in doing so, we will look at following points

  • Getting started with Web API in Asp.net Web form application
  • Installing Prerequisites
  • Read/Search operation in detail
  • Add/Insert operation in detail
  • Update and Delete operation in detail

Getting started with Web API in Asp.net Web form application

Note: Please note that this section is writen based on MVC 4 beta version (which is most recent at the time of this writing). If there's newer MVC version available, then the points explained in this section might not stand true.

Since, Web API is shipped as part of MVC 4 beta version, we would require to install MVC 4 beta first (again, this dosen't mean you cannot use Web API in web form application).

Before going ahead with downloading and installing MVC 4 beta, note that MVC 4 beta is not compatible with .Net framework 4.5 developer preview. That means, if you real enthusiast and had already installed .Net framework 4.5 developer preview then you now have to get rid of it. So, uninstall framework 4.5 first.

MVC 4 beta download link is available on this page. Follow the link and get the MVC 4 beta downloaded on your machine.

Now, lets move ahead and create a new web site project. Name it as WebAPITest. A new Web site project with default files should start. Now, add a standard folder App_Code in the project.

To create Web API support in the project, a class file requires to be added in the project which inherits from class ApiController. MVC 4 makes available a file template for this class. If MVC is unknown territory for you then don't confuse yourself with word "Controller".

Right click on the project in solution explorer and select "Add New Item"

In the Add New Item dialogue, select file template named "Web API Controller Class" as displayed below and give the name as EmployeeController. Note that, the name of Web API controller should end with Controller.

This will add a Web API controller file in the App_Code folder. By default it would have created methods like Get, Put, Post and Delete. The default controller class definition has some issue. The name of namespace has a dot character as prefix; remove that dot (Henrik's this blog agrees that it is a bug)

The final adjustment requires to be done is in Global.asax file. This will add a route in global route table and the request to Web API would be routed to API controller class.

<%@ Application Language="C#" %>
<%@ Import Namespace="System.Web.Routing" %>
<%@ Import Namespace="System.Web.Http" %>
    
<script runat="server">    
     
    void Application_Start(object sender, EventArgs e)
    {
        RouteTable.Routes.MapHttpRoute(
           name: "DefaultApi",
           routeTemplate: "api/{controller}/{id}",
           defaults: new { id = System.Web.Http.RouteParameter.Optional }
       );        
    }

That's it we are now ready to test Web API. But wait, there's nothing in the Web API methods. Before looking at CRUD implementation using Web API, lets check few more prerequisites.

Installing Prerequisites

This is not official list of required prerequisites and you can use Web API without these components/files. But I am going to use them in the demo and if you are trying to create a Web API demo by following this article then you will need them :)

Using Json.Net : Json.Net is framework which works as Json formatter which we would require for returning data in Json format from our Api controller methods.

To install Json.Net, you don't have to go anywhere, simply open Package manger console (in menu bar, go to View -> Other windows -> Package Manager Console) and type command as displayed below.

After installing Json.Net, we will create a Formatter. The Json formatter would do the task of serializing data to read and write. Luckily, Henrik again has some ready stuff for us here. In this blog, Henrik has posted a formatter code using Json.Net. I have used the same code in this demo with change in couple of lines.

Create a new file in the App_Code folder and name it as JsonNetFormatter.cs. Copy and paste below code, in this new file.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Net.Http.Formatting;
using Newtonsoft.Json;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Net;

/// <summary>
/// Summary description for JsonNetFormatter
/// </summary>
public class JsonNetFormatter : MediaTypeFormatter
{
    private JsonSerializerSettings _jsonSerializerSettings;

    public JsonNetFormatter()
    {
        _jsonSerializerSettings = new JsonSerializerSettings();

        // Fill out the mediatype and encoding we support 
        SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/json"));
        Encoding = new UTF8Encoding(false, true);
    }

    protected override bool CanReadType(Type type)
    {
        if (type == typeof(IKeyValueModel))
        {
            return false;
        }

        return true;
    }

    protected override bool CanWriteType(Type type)
    {
        return true;
    }

    protected override Task<object> OnReadFromStreamAsync(Type type, Stream stream, HttpContentHeaders contentHeaders, FormatterContext formatterContext)
    {
        // Create a serializer 
        JsonSerializer serializer = JsonSerializer.Create(_jsonSerializerSettings);

        // Create task reading the content 
        return Task.Factory.StartNew(() =>
        {
            using (StreamReader streamReader = new StreamReader(stream, Encoding))
            {
                using (JsonTextReader jsonTextReader = new JsonTextReader(streamReader))
                {
                    return serializer.Deserialize(jsonTextReader, type);
                }
            }
        });
    }

    protected override Task OnWriteToStreamAsync(Type type, object value, Stream stream, HttpContentHeaders contentHeaders, FormatterContext formatterContext, TransportContext transportContext)
    {
        // Create a serializer 
        JsonSerializer serializer = JsonSerializer.Create(_jsonSerializerSettings);

        // Create task writing the serialized content 
        return Task.Factory.StartNew(() =>
        {
            using (StreamWriter streamWriter = new StreamWriter(stream, Encoding))
            {
                using (JsonTextWriter jsonTextWriter = new JsonTextWriter(streamWriter))
                {
                    serializer.Serialize(jsonTextWriter, value);
                }
            }
        });
    }
}

After creating the Json formatter, this has to be added as first formatter in configuration. To do that, go to Global.asax file and add these two lines in the Application_start event.

var config = GlobalConfiguration.Configuration;
config.Formatters[0] = new JsonNetFormatter();

That's it.

Using Json.js :

While doing Insert/Update operation, We will serialize Javascript object into string and send it to Web API controller. For doing the serialization, we will use the JSON.Stringify method.

Either make sure that you are using jQuery version more than 1.5 or use additional Json.js file from this link on GitHub and download the Json.js file. We will look at its use in Create operation.

Read/Search operation in detail

For creating the demo application, we will use an short employee table named "Emp" as below.

To read the database table in the application, you can write a data read/write logic and create a DAL layer using ADO.Net classes or use ORM tool of your choice etc.

For this demo, I am going to use Entity Framework (ORM tool of my choice :). Add New "ADO.Net Entity Data Model" file in your project and drag the table single "Emp" in the designer and name the Entity as TestDBEntities. Save the file and we should be ready to use Entity class for read/update/delete operations

Now moving to the Web API methods implementation. The Get() method of controller class would be called whenever the HTTP GET is used while calling the Web API. Open the EmployeeController.cs file and change the Get() method as below.

        EmployeeDBModel.TestDBEntities _dbContext;
        // GET /api/<controller>
        public IEnumerable<EmployeeDBModel.emp> Get()
        {            
            _dbContext = new EmployeeDBModel.TestDBEntities();
            return _dbContext.emps.AsQueryable();            
        }

Note that we have changed the signature of Get method to return IEnumerable Emp class of EmployeeDBMoel entity and we are returning Emps object in the form of AsQueryable. 

Note: Since default Json serializer could not serialize the EF object, if you have not built JsonFormatter as I did in the section "Installing PreRequisites" then, you might face issue while directly retuning EF object from Get method as above (This stands true only till MVC 4 beta version and might not require in future versions)

The Get method would return a Json object to a caller. To make a call to this web API method and consume the returned data, lets build simple aspx/html in our web application. Name the form as SearchEmployee.aspx and add following Html code in the form

<html>
<head>
    <script src="Scripts/jquery-1.7.1.min.js" type="text/javascript"></script>
    <script type="text/javascript">
        $(document).ready(function () {
            // Call ajax getJSON method
            //first parameter specifies url to be called
            //second parameter indicates callback function which is executed when request is successful
            $.getJSON("api/employee", function (data) {

                //declare a varialbe which holds html string to be appnended to create a table structure from returned data
                var strHTML = "<table width='50%' style='border-width:thin;font-family:Verdana;font-size:small;border-collapse:collapse' border='1'>";
                strHTML += "<tr><th>Employee ID</th><th>Employee Name</th><th>Job Title</th></tr>";

                //iterate over every object returened using each function 
                $.each(data, function (key, val) {
                    //Form a html row string based on the returned Json object
                    strHTML += "<tr>";
                    strHTML += "<td width='20%' style='border:1 solid gray;'>" + val.empno + "</td>";
                    strHTML += "<td width='20%' style='border:1 solid gray;'>" + val.ename + "</td>";
                    strHTML += "<td width='20%' style='border:1 solid gray;'>" + val.job + "</td>";
                    strHTML += "</tr>";
                });
                //append html table to div
                $('#employees').append(strHTML);
            });
        });
    </script>
    <title>ASP.NET Web API</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <h1>
            Employee List</h1>
    </div>
    <div id="employees">
    </div>
    </form>
</body>
</html>

In JQuery document.ready method getJSON method uses a uri "API/Employee". We are calling Web API with name as Employee because our controller class is named as "EmployeeController". If you had defined controller class as something different, then you will have to change the URL used in getJSON method.

The request would then be forwarded to EmployeeController class. But, and since getJSON method sends a GET http request,the request would be forwarded to Get() method of controller. The returned data would be in Json format and would be displayed in html table format as below

Getting record by ID

We can extend the Get method so that instead of getting all records, get only perticular record by ID. So, effectively we can create a search operation. The logic is to call a Web API method in following format.

API/Employee/<Id of the record to be searched>

To support get by ID functionality, add Get method in the EmployeeController class which expects id parameter (modify existing Get method with parameter) and returns EF object "Emp".

public EmployeeDBModel.emp Get(int id)
        {
            _dbContext = new EmployeeDBModel.TestDBEntities();
            return (from employee in _dbContext.emps
                   where employee.empno==id
                   select employee).First();
        }

This Get method will filter table based on id parameter passed and return single EF object.

At client side, we will call the same jQuery getJSON method but, this time the calling URL would have Id of the record to be searched appended at the end. Also, there is a provision for user to enter a Id to be searched and text fields to populate the returned data.

Add following code in aspx page and Javascript function which will be called on search button click.

<script type="text/javascript">
        function GetEmployeeById() {
            // Call ajax getJSON method
            //first parameter specifies url of the Web API controller and id entered by user
            //second parameter indicates callback function which is executed when request is successful
            $.getJSON("api/employee/" + $("#txtsearch").val(),
         function (data) {
             //set returned data in corrosponding text fields
             $("#txtEmpNumber").val(data.empno);
             $("#txtEmployeeName").val(data.ename);
             $("#txtJob").val(data.job);
         });
            return false;
        }
   </script>

    <div>
        <h1>
            Search Employee</h1>
    </div>
    <fieldset class="register">
        <div>
            <asp:Label ID="Label1" runat="server" AssociatedControlID="txtEmpNumber">Enter employee number to search:</asp:Label>
            <asp:TextBox ID="txtsearch" runat="server" CssClass="textEntry">
            </asp:TextBox>
            <asp:Button ID="btnsearch" runat="server" Text="Search Employee" OnClientClick="return GetEmployeeById()" />
            <hr />
        </div>
        <div>
            <asp:Label ID="EmpNumber" runat="server" AssociatedControlID="txtEmpNumber">Employee Number:</asp:Label>
        </div>
        <div>
            <asp:TextBox ID="txtEmpNumber" runat="server" CssClass="textEntry" Enabled="false">
            </asp:TextBox>
        </div>
        <div>
            <asp:Label ID="EmployeeName" runat="server" AssociatedControlID="txtEmployeeName">Employee Name:</asp:Label>
        </div>
        <div>
            <asp:TextBox ID="txtEmployeeName" runat="server" CssClass="textEntry">
            </asp:TextBox>
        </div>
        <div>
            <asp:Label ID="Job" runat="server" AssociatedControlID="txtJob">
                Job Title
            </asp:Label>
        </div>
        <div>
            <asp:TextBox ID="txtJob" runat="server" CssClass="textEntry">
            </asp:TextBox>
        </div>

Add/Insert operation in detail

Add/Insert operation requires that you submit the data from Json as a HTTP Post and hence, it requires to use Post method of Web API controller. In addition of calling a Post method, Web API allows to define different parts of response header. Hence, we can define what HTTP status code should be returned with response from Web API.

As per the W3 standard, If the new resource is being created due to a http reques, then the response should indicate that with the HTTP status code 201 (check this). This just an example. In summary now we can manipulate the response status code based on nature of request/response.

The definition of Post method would look something like this

public HttpResponseMessage<EmployeeDBModel.emp> Post(EmployeeDBModel.emp employee)
        {
            //create entity object
            _dbContext = new EmployeeDBModel.TestDBEntities();
            EmployeeDBModel.emp objEmployee = new EmployeeDBModel.emp();
            //Assign respective values submitted by Json object to entity object
            objEmployee.ename = employee.ename;
            objEmployee.dept = 1;            
            objEmployee.job = employee.job;
            objEmployee.mgr = 1;
            //Add updated object to entity
            _dbContext.AddToemps(objEmployee);
            //save new entity object
            _dbContext.SaveChanges();
            //Create new Httpresponsemessage variable from entity object
            //Use status code as Created (201) to indicate new object creation
            var response = new HttpResponseMessage<EmployeeDBModel.emp>(employee, HttpStatusCode.Created);
            string uri = Url.Route(null, new { id = employee.empno });
            //Add url of new resource in the HTTP header's location property
            //This will add location as http://hostname/API/Employee/<id of new record>
            response.Headers.Location = new Uri(Request.RequestUri, uri);
            //return respose object
            return response;
        }

Since, the Post method accepts parameter of EF type "Emp", we will have to form the Json object on the client side and send it via jQuery Ajax request.

Use below Javascript and html code for doing capturing the user input and sending the data in the post method.

<script type="text/javascript">
        function AddEmployee() {
            //create a Json object based on data entered by user
            var newEmployee = {
                ename: $("#txtEmployeeName").val(),
                job: $("#txtJob").val()
            };
            //call jQuery Ajax method which calls Json.stringify method to convert 
            //the Json object into string and send it with post method
            $.ajax({
                url: "api/employee",
                data: JSON.stringify(newEmployee),
                type: "POST",
                contentType: "application/json;charset=utf-8",
                statusCode: {
                    //Web API Post method returns status code as 201
                    201: function () {
                        alert("New employee added successfully");
                    }
                }
            });
            return false;
        }
    </script>

    <div>
        <h1>
            Add Employee</h1>
    </div>
    <fieldset class="register" style="width: 50%">
        <div>
            <asp:Label ID="EmployeeName" runat="server" AssociatedControlID="txtEmployeeName">Employee Name:</asp:Label>
        </div>
        <div>
            <asp:TextBox ID="txtEmployeeName" runat="server" CssClass="textEntry">
            </asp:TextBox>
        </div>
        <div>
            <asp:Label ID="Job" runat="server" AssociatedControlID="txtJob">
                Job Title
            </asp:Label>
        </div>
        <div>
            <asp:TextBox ID="txtJob" runat="server" CssClass="textEntry">
            </asp:TextBox>
        </div>
        <div>
            <p>
                <asp:Button ID="btnAdd" runat="server" CssClass="submitButton" Text="Add Employee"
                    OnClientClick="return AddEmployee();"></asp:Button>
            </p>
        </div>
    </fieldset>

Run the page and visit the AddEmployee form. Enter the employee data and click on the Add Employee button. It should display "Employee added successfully" message and the employee record should have added in the database.

Update and Delete operation in detail

In Update and Delete method, the only thing changes is that HTTP type "PUT" is used in Ajax call and the Put method of Web API implments logic of updating database table.

Simillarly, in case of delete operation DELETE type is used in Ajax call on client side and Delete method of Web API controller hold the data deletion logic.

lets look at the update and delete methods of Web API controller. Both methods accept EF object "Emp". Since, status code 200 is by default returned by any HTTP response, it makes sense to return any data from Put method.

Below is the short code of Put (update) and Delete methods in Web API controller.

public void Put(EmployeeDBModel.emp employee)
        {
            _dbContext = new EmployeeDBModel.TestDBEntities();
            var empObj = _dbContext.emps.First(c => c.empno == employee.empno);
            empObj.ename = employee.ename;
            empObj.job = employee.job;
            _dbContext.SaveChanges();
        }

        // DELETE /api/<controller>/5
        public HttpResponseMessage Delete(EmployeeDBModel.emp employee)
        {
            _dbContext = new EmployeeDBModel.TestDBEntities();
            var empObj = _dbContext.emps.First(c => c.empno == employee.empno);
            _dbContext.DeleteObject(empObj);            
            _dbContext.SaveChanges();
        }

To allow user to update and delete the records from the front end, we will use the same form which we created for the searching data by id. In the same form, add update and delete buttons as below. So that, once user searches for perticular record and data is populated in the textfields, user can modify the data and click on update button to make changes or click on Delete button to delete the data.

<div>
   <p>
       <asp:Button ID="btnUpdate" runat="server" CssClass="submitButton" Text="Update Employee"
          OnClientClick="return UpdateEmployee()"></asp:Button>

       <asp:Button ID="btnDelete" runat="server" CssClass="submitButton" Text="Delete Employee"
          OnClientClick="return DeleteEmployee()"></asp:Button>
   </p>
</div>

Define Javascript function as below for both Update and Delete operations.

<script type="text/javascript">
        function UpdateEmployee() {
            //create a Json object based on data entered by user
            var newEmployee = {
                empno: $("#txtEmpNumber").val(),
                ename: $("#txtEmployeeName").val(),
                job: $("#txtJob").val()
            };
            //call jQuery Ajax method which calls Json.stringify method to convert 
            //the Json object into string and send it with post method
            //The type of request is set as PUT which calls Put method of controller class
            $.ajax({
                url: "api/employee",
                data: JSON.stringify(newEmployee),
                type: "PUT",
                contentType: "application/json;charset=utf-8",
                statusCode: {
                    200: function (employee) {
                        alert("Updated successfully");
                    }
                }
            });
            return false;
        }

        function DeleteEmployee() {
            //create a Json object with id of the record to be deleted
            var deleteEmployee = {
                empno: $("#txtEmpNumber").val()
            };
            //call jQuery Ajax method which calls Json.stringify method to convert 
            //the Json object into string and send it with post method
            //The type of request is set as DELETE which calls Delete method of controller class
            $.ajax({
                url: "api/employee",
                data: JSON.stringify(deleteEmployee),
                type: "DELETE",
                contentType: "application/json;charset=utf-8",
                statusCode: {
                    200: function (employee) {
                        $("#txtEmpNumber").val('');
                        $("#txtEmployeeName").val('');
                        $("#txtJob").val('');
                        alert("Employee record deleted successfully");
                    }
                }
            });
            return false;
        }
    </script>

Run the web page and first search the employee record. After employee data is populated in respective fields, modify any of the record and click on Update button. This will update the record and display alert message.

Simillarly, clicking on the Delete button will delete the respective record and display the "deleted successfully" message and will delete the employee record with ID set in Employee Number field.

That's it! It covers basic CRUD operations using Web API

Conclusion

Web API is not new. It is possible to create a RESTful services using WCF Web API also. But, since Web API is part of Asp.net now, it is possible for developers who are not aware about WCF to take advantage of Web API framework to create RESTful HTTP services which can be consumed by broader consumers than traditional Asp.net Web Service.

Now a days more and more services are being built as RESTfult HTTP. It is not only easy to build one but also makes more sense for wide range of HTTP clients like handheld devices/mobile devices. Asp.net Web API is like a need of time and worth looking at.

Hope you enjoyed reading the article. Please provide a comment to point out any descripencies in the writing. Thank you for visiting my site :)

About Me

You are visiting personal website of Kedar (KK)

Please go here to know more about me

Disclaimer

The opinions expressed here represent my own and not those of my past or present employers.

The concept/code provided on this site may not work as described. If you are using any code provided on this site. Then, please test it thoroughly. I shall not be responsible for any issues arising in the code. 

Month List