Implementing AJAX in ASP.NET MVC - CodeProject

:

Sample Image - maximum width is 600 pixels

Introduction

This tip explains how we can implement AJAX in ASP.NET MVC. Here, I have attempted to explain the concept of partial page updates using a partial view to display product details asynchronously. For simplicity, I have stored details of three products statically in a list. The application searches the product code entered by a user and displays the corresponding product details.

Background

Traditional web applications rely on synchronous method calls to process data. The entire web page is posted to the server each time data is submitted through the page, causing performance delays.

This problem can be overcome by using AJAX. AJAX allows web applications to call methods asynchronously. Instead of posting the entire page to the web server, only the required data is posted. This improves the overall performance of the web applications.

Using the Code

Begin by creating a new ASP.NET MVC4 project as follows:

We will use a model class to display data in a partial view. For this, we have to add a Product class in the Models folder as follows by right clicking on the Models folder and selecting the Add Class option:

Following is the code of the Product class:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace AJAXDemo.Models
{
    public class Product
    {
        public string ProdCode
        {
            get;
            set;
        }
        public string ProdName
        {
            get;
            set;
        }
        public int ProdQty
        {
            get;
            set;
        }
    }
}

Then, add new layout in the Shared folder under the Views folder as follows:

Following is the code of the _Layout.cshtml file:

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>_Layout</title>
    @RenderSection("scripts")
</head>
<body>
    <div>
        @RenderBody()
    </div>
</body>
</html>

This layout will be used by the Index view. In this layout, the RenderSection() method defines a placeholder for the scripts section and the RenderBody() method defines a placeholder for the main content of the Index view.

Add a new controller as follows by right clicking on the Controllers folder:

Following is the code of the Index() method:

public ActionResult Index()
{
   Product p1 = new Product { ProdCode = "P001", ProdName = "Mobile", ProdQty = 75 };
   Product p2 = new Product { ProdCode = "P002", ProdName = "Laptop", ProdQty = 125 };
   Product p3 = new Product { ProdCode = "P003", ProdName = "Netbook", ProdQty = 100 };
   prodList.Add(p1);
   prodList.Add(p2);
   prodList.Add(p3);
   return View();
}

This code creates three product objects and adds them to a static list called prodList which is declared at the class level and it renders the view associated with the Index view.

Add the view corresponding to the above action method as follows by right clicking on the Index() method in the controller:
(Note: Remember to select the layout page while adding the Index view.)

Following is the code of the Index.cshtml view:

@{
    ViewBag.Title = "Index";
    Layout = "~/Views/Shared/_Layout.cshtml";
}
@section scripts
{
    <script type="text/javascript" src="~/Scripts/jquery-1.7.1.js"></script>
    <script type="text/javascript" src="~/Scripts/jquery.unobtrusive-ajax.js"></script>
}

<h2>Index</h2>
@Ajax.BeginForm("ShowDetails","Ajax",
     new AjaxOptions
     { HttpMethod = "POST", UpdateTargetId = "div1", 
     InsertionMode = InsertionMode.Replace, LoadingElementId = "waitimage" })
<h1>Enter Product Code</h1>
<h2>
    Product Code: @Html.TextBox("txtCode")<br />
    <input type="submit" value="Show Details" />
    <input type="reset" value="Clear"/>
</h2>
@{Html.EndForm();}
<br />
<img id="waitimage" src="~/Images/loading42.gif" style="display:none" />
<br />
<div id="div1">
</div>

The above view references the jquery.unobtrusive-ajax.js script to implement the AJAX functionality. It also uses a div with the id "div1" to display the requested product details. It uses the Ajax.BeginForm() helper method to accept product code and submit it asynchronously. The first parameter of the Ajax.BeginForm() method specifies the name of the action method to be invoked to process the input data, the second parameter specifies the name of the controller and the third parameter specifies the AjaxOptions to be used. In the AjaxOptions, the HttpMethod property specifies the HTTP method to be used, the UpdateTargetId property specifies the ID of the div element where the partial view will be displayed, the InsertionMode property specifies the mode of insertion of the partial view, and the LoadingElemetId property specifies the ID of the image to be displayed while waiting for the asynchronous call to be completed and the view to be rendered.

The InsertionMode property can have one of the following values:

  • InsertionMode.InsertAfter - The new details are added after the existing details
  • InsertionMode.InsertBefore - The new details are added before the existing details
  • InsertionMode.Replace - The new details replace the existing details

In order to process the input and search the product code entered by the user, we add a method in the controller which returns a partial view as follows:

public PartialViewResult ShowDetails()
{
   System.Threading.Thread.Sleep(3000);
   string code = Request.Form["txtCode"];
   Product prod = new Product();
   foreach(Product p in prodList)
   {
       if (p.ProdCode == code)
       {
           prod = p;
           break;
       }
   }
   return PartialView("_ShowDetails", prod);
}

The above code searches the entered product code and returns the product corresponding to it using a partial view. It uses the Thread.Sleep() method to simulate delay in fetching the product details. This allows you to view the page loading animation while waiting for the asynchronous method call to complete.

In order to display the product details, we have to add a strongly typed partial view as follows by right clicking on the method and selecting the Add View option:

Following is the code of the _ShowDetails view:

@model AJAXDemo.Models.Product

@if(Model.ProdCode==null)
{
    <h1>Invalid Product Code</h1>
}
else
{
    <h1>Product Details</h1>
    <h2>
        Product Code: @Model.ProdCode<br />
        Product Name: @Model.ProdName<br />
        Product Quantity: @Model.ProdQty<br />
    </h2>
}

The above code displays the product details if the product code is found and the message "Invalid Product Code" if it is not found.

Before executing the application, we have to specify the routing information in the RouteConfig.cs file in the App_Start folder as follows:

routes.MapRoute(
                name: "Default",
                url: "{controller}/{action}/{id}",
                defaults: new { controller = "Ajax", action = "Index", id = UrlParameter.Optional }
            );

Also, we need to enable unobtrusive JavaScript by adding the "UnobtrusiveJavaScriptEnabled" key under the <configuration> element in the Web.config file as follows:

<appSettings>
    <add key="webpages:Version" value="2.0.0.0" />
    <add key="webpages:Enabled" value="false" />
    <add key="PreserveLoginUrl" value="true" />
    <add key="ClientValidationEnabled" value="true" />
    <add key="UnobtrusiveJavaScriptEnabled" value="true" />
</appSettings>

On execution, the application produces the following output:

Entering a product code and clicking the submit button displays the corresponding product details asynchronously.

Points of Interest

AJAX is a very important feature of web applications and it provides significant performance advantage over traditional web applications.

I have developed the application using Microsoft Visual Studio Express 2013 for Web.