Channels ▼
RSS

Database

Supercharging ASP.NET Web Form Apps


The majority of ASP.NET websites are built using the ASP.NET Web Forms model. It provides a simple, stateful abstraction over the stateless HTTP protocol, and focuses on server-side processing. Recently, websites have focused more on a client-side model with the use of JavaScript, AJAX, and REST-style services. With the introduction of the ASP.NET Web API in ASP.NET 4.5, it is now possible to add advanced client-side functionality to existing sites, while retaining many of the benefits of the Web Forms model.

A Simple Web Forms Application

To understand how to supercharge an existing Web Forms application with the ASP.NET Web API, let's first take a brief look at a Web Forms app that I'll use as an example. Figure 1 shows the list view of a simple Tasks application, which was created using the new Web Forms template shipped as part of Visual Studio 2012.

Super-Charging ASP.NET Web Form Apps
Figure 1: The Tasks page in list mode.

The Add New Task button and the Edit links in the Grid allow the user to add new tasks or edit the relevant existing tasks.

Assume that you have been given a new requirement: Instead of just displaying the "Is Complete" status of the task, the application should display a checkbox and allow users to update the status of the task (rather than having to click "Edit" and be redirected to the edit page). 

You could fulfill this requirement by using a checkbox column in the ASP.NET GridView control and switching the GridView into Edit mode, but this would require the use of server post-backs and would trigger a complete refresh of the grid whenever a task is updated. Instead, let's use some JavaScript in the client and the ASP.NET Web API to demonstrate how to make the updates more modern and responsive.

Adding the ASP.NET Web API using Nuget

ASP.NET Web API was released in conjunction with the .NET 4.5/Visual Studio 2012 release, but it doesn't actually require .NET 4.5. Instead, it's built against the earlier .NET 4.0 release.  To add Web API support to an existing project, we can use Nuget to install the latest version, either via the website or via one of the integration points such as Manage Nuget Packages in Visual Studio (Figure 2).

Super-Charging ASP.NET Web Form Apps
Figure 2: Adding the Web API using Nuget.

This ensures you have the relevant components installed and will allow you to update those components if newer versions of the ASP.NET Web API are released. Note that, depending on what features of the ASP.NET Web API you want to use, you may still have to add some assembly references manually.

Adding a Web API Controller

The first step in adding our new feature using the Web API is to create a Web API Controller class (Figure 3). The Web API has some similarities to ASP.NET MVC in that the new class extends the ApiController base class and, by convention, is called TasksController.  I will show how this convention works when we review the URI that needs to be called for our methods to be executed.

Super-Charging ASP.NET Web Form Apps
Figure 3: Adding a new Web API controller class.

In the controller class, I will create a single method, UpdateStatus, that updates the task and changes the value of the IsComplete property, taking the ID as a single parameter (Listing One).  As this is an update operation, I follow the convention of making the action method work with the PUT HTTP method (verb).  I indicate that by using the HttpPut attribute on the method.

Listing One: The UpdateStatus Method

[HttpPut]
public HttpResponseMessage UpdateStatus(int id)
{
    try
    {
        var db = new TasksContext();

        Task task = (from t in db.Tasks
                     where t.TaskID == id
                     select t).SingleOrDefault();

        if (task == null)
        {
            return Request.CreateResponse(HttpStatusCode.NotFound); ;
        }

        task.IsComplete = !task.IsComplete;

        db.SaveChanges();

        return Request.CreateResponse(HttpStatusCode.OK);
    }
    catch (Exception exc)
    {
        return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, exc);
    }
}

In this simple example, I am the using Entity Framework for persistence, and the first few lines of this method retrieve the task to be updated. As long as I have a valid task (that is, the task is not null), I simply change the value of the IsComplete property and save the changes. This is fairly straightforward Entity Framework code. 

If the update is successful, I create a new HttpResponseMessage with the OK status code (200), and this response is sent back to the caller.  If there are exceptions, I create an HttpResponseMessage with the appropriate status code and, in the case of an Internal Server Error, details of the exception.

Adding Routing Information to Application_Start

Now that I have a Web API Controller class to route to, I need to set up the routes in the Application_Start event handler, so the Web API can execute the correct method. ASP.NET Web API routes are similar to ASP.NET MVC Routes. Two example routes are shown in Listing Two.

Listing Two: Adding ASP.NET Web API Routes to Application_Start.

RouteTable.Routes.MapHttpRoute(
    name: "DefaultApi",
    routeTemplate: "api/{controller}/{id}",
    defaults: new { id = RouteParameter.Optional }
);

RouteTable.Routes.MapHttpRoute(
    name: "TasksApi",
    routeTemplate: "api/{controller}/{action}/{id}",
    defaults: new { id = RouteParameter.Optional }
);

The first route is the default Web API route. Using this route, it's possible to use URIs like api/Tasks/5.

The {controller} place-holder routes control to the relevant Web API controller class. In the aforementioned example, it will be routed to the TasksController, and "api/products" would route to the ProductsController.

If used with the GET HTTP method (or verb), this URI is mapped to an action method that starts with the prefix Get, such as GetTask or GetTaskById, and the parameter (5) is passed as the ID parameter of the action method. Similarly, if used with the DELETE HTTP method, this URI is mapped to an action method that starts with the prefix Delete, such as DeleteTask or DeleteTaskById. Note that as long as the method has the correct prefix, control is routed to the correct action method regardless of the rest of the name. Issues arise only if the routing is ambiguous because there are two or more methods that start with the same HTTP method prefix: GetTaskById and GetTaskByCategory.

I could have followed this convention and used the Put prefix in the name of the action method I created in Listing One, but the action method does not contain any of these HTTP method prefixes. I can handle this by defining a second route to send control explicitly to a specific action. In this case, the {action} place-holder maps to the name of the action method, so the URI would need to be api/Tasks/UpdateStatus/5.

This URI will now route to the UpdateStatus method of the TasksController, passing the value 5 as the taskId parameter.


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.
 

Video