Thứ Sáu, 2 tháng 3, 2012

Implementing AutoPostBack in ASP.NET MVC

Introduction

ASP.NET Web Forms allow you to automatically post a form back to the server when the selection in a DropDownList control changes. This is achieved by setting the AutoPostBack property of the DropDownList control. The AutoPostBack feature is a handy way to refresh a page when data being displayed is dependent on the selection made in the DropDownList. In ASP.NET MVC applications you need to add this feature programmatically since they often use plain HTML markup to render a DropDownList. This article explains how AutoPostBack can be implemented in ASP.NET MVC.

Two Flavors of AutoPostBack

AutoPostBack refers to submitting a POST request to the server automatically when a certain client side event of an HTML form element is triggered. Consider a case where an HTML page consists of a DropDownList (<SELECT> element) and a table. Depending on the item selected in the DropDownList you need to fetch data from SQL server and display it in the table. One way to do this is to select an item from the DropDownList and click on a "Submit" button so as to send the selection made to the server. A more logical arrangement would be to submit the form as soon as the selection in the DropDownList changes. This later mechanism is called "AutoPostBack". An AutoPostBack can be of two types :
  • Full page AutoPostBack
  • Partial page AutoPostBack
In the case of a full page AutoPostBack, the entire web page is POSTed to the server when selection in a DropDownList changes. This arrangement is suitable in cases where a large part of the page will be affected due to the change in the selection. The advantage of this approach is that it requires little client side JavaScript code. However, the downside is that the entire page will be refreshed thus requiring more time and bandwidth to re-display the page.
In the latter case, i.e., partial page AutoPostBack, instead of submitting the entire page, an AJAX call is made to the server side code to retrieve dependent data. Upon receiving the data the page is updated with the new data using a client side script. The advantage of this method is that the entire form is not submitted to the server. Instead only the required data is POSTed to the server resulting in much lesser traffic and time. The downside is that a reasonable amount of client side code may be required to fetch the data and update the page.

The remainder of this article will show you how to implement both the types of AutoPostBack in an ASP.NET MVC application.

Creating a Sample Application

First of all let's create an ASP.NET MVC application for demonstrating AutoPostBack functionality. Your application will consist of a simple view as shown below:
AutoPostBAck in a DropDownList
Figure 1: AutoPostBack in a DropDownList
The web page consists of two DropDownList elements and a table. Both of the DropDownList elements display a list of cities from the Customers table of Northwind database. The first DropDownList causes full page AutoPostBack whereas the latter DropDownList causes partial page AutoPostBack. Depending on the city selected in the DropDownList the table shows the CompanyName column of the relevant customer records.
To begin developing the application, create an empty ASP.NET MVC application using ASPX view engine. Then add an ADO.NET Entity Data Model to the Models folder of the web application. Make sure to select the Customers table of the Northwind database during model creation.
Choose Your Database Objects
(Full Size Image)
Figure 2: Choose Your Database Objects
Once created, your Customer entity class should look like this:
Customer Entity class
Figure 3: Customer Entity class
Next, add a new controller in the Controllers folder and name it HomeController.
namespace AutoPostbackInMVCDemo.Controllers

{

    public class HomeController : Controller

    {

       ...

    }

}
The HomeController will contain a couple of helper methods and action methods.

Adding Helper Methods

The helper methods do the job of retrieving Customer data using the data model and are shown below :
public IQueryable<Customer> GetCustomersByCity(string city)

{

    NorthwindEntities db=new NorthwindEntities();

    var data = from item in db.Customers

                where item.City == city

                select item;

    return data;

}

 

public IQueryable<Customer> GetAllCustomers()

{

    NorthwindEntities db = new NorthwindEntities();

    var data = from item in db.Customers

                select item;

    return data;

}

 

public string[] GetCityNames()

{

    NorthwindEntities db = new NorthwindEntities();

    var data = (from item in db.Customers

                select item.City).Distinct();

    return data.ToArray();

}
The GetAllCustomers() helper method returns all of the customers from the Customers table whereas GetCustomersByCity() method returns only the customers belonging to a specified City name. The GetCityNames() method returns an array of unique city names from the Customers table. Notice the use of Distinct() method to retrieve only the unique city names. These helper methods are used in action methods of the Home controller. The action methods are discussed next.

Adding Action Methods

You need three action methods viz. ShowCustomers(), ShowCustomers(city) and GetCustomersByCityAJAX(city).
[HttpGet]

public ActionResult ShowCustomers()

{

    string[] citynames = GetCityNames();

    ViewBag.CityNames = citynames;

    ViewBag.SelectedCity = citynames[0];

    ViewBag.Customers = GetAllCustomers();

    return View();

}
The ShowCustomers() action method is marked with the [HttpGet] attribute indicating that it will handle GET requests. Inside the method you call the GetAllCustomers() and GetCityNames() helper methods created earlier. It also sets three ViewBag properties viz. CityNames, SelectedCity and Customers. The CityNames property is an array of strings that stores all the unique city names. The SelectedCity property indicates the current selection of the city so that DropDownList can set the initial city name accordingly. Since ShowCustomers() will be called with the first ever request to the page, you set SelectedCity to the first city in the array. The Customers property contains a list of all the Customer objects.
The ShowCustomers(city) action method is called for POST requests and is shown below :
[HttpPost]

public ActionResult ShowCustomers(string city)

{

    ViewBag.CityNames = GetCityNames();

    ViewBag.SelectedCity = city;

    ViewBag.Customers = GetCustomersByCity(city);

    return View();

}
As you can see, ShowCustomers(city) receives a string parameter - city - that indicates the city name selected by the user in the DropDownList. Inside, it calls the GetCityNames() and GetCustomersByCity() helper methods as before. The ViewBag properties are also set. Notice that this time the SelectedCity property is set to the city selected by the user. This way View can preserve the user selection even after a postback.
The GetCustomersByCityAJAX() action method is a special method in that it will be called using client side jQuery code. The GetCustomersByCityAJAX() action method is shown below :
[HttpPost]

public JsonResult GetCustomersByCityAJAX(string city)

{

    NorthwindEntities db = new NorthwindEntities();

    var data = from item in db.Customers

                where item.City == city

                select item;

    return Json(data.ToArray());

}
Notice that the return type of GetCustomersByCityAJAX() method is JsonResult. Since this method will be called using jQuery code, you need to return data in JSON format so that it can be used in the client side script. Also notice how the data is returned using the Json() method. The Json() method accepts an object to be serialized in the JSON format and then returns it as a JsonResult. The GetCustomersByCityAJAX() method is marked with the [HttpPost] attribute because you will send a POST request from the jQuery code while calling this method.
Now, right click on ShowCustomers() action method and select the "Add View" menu option. Then add a strongly typed view named ShowCustomers by selecting Customer data model class.
Add View
Figure 4: Add View

Implementing Full Page AutoPostBack

In this section you will add full page AutoPostBack functionality to a DropDownList. Open the ShowCustomers view and add the following markup to it:
<h1>AutoPostBack in a DropDownList</h1>

<% using (Html.BeginForm()){%>

...

<%= Html.DropDownList("city", new SelectList(ViewBag.CityNames, ViewBag.SelectedCity), new { onchange = "form.submit();" })%>

<%

    IQueryable<Customer> customers = ViewBag.Customers as IQueryable<Customer>;

%>

<table id="customerTable" border="1" cellpadding="6">

<tr><th>Company Name</th></tr>

<%

    foreach (Customer c in customers)

    {

%>

<tr><td><%= c.CompanyName%></td></tr>

<% 

    }

    }

%>

</table>
Notice the line marked in bold letters. This line makes use of the DropDownList HTML helper to render a <SELECT> element. Have a look at the last parameter of the DropDownList() call. It indicates a list of HTML attributes that are to be rendered for the element and we specify the onchange event handler there. The onchange event handler simply calls the submit() method of the form object so as to submit the form. Also notice that the name of the DropDownList is city - same as the parameter name of ShowCustomers action method (POST version).
The remaining markup of the view simply iterates through Customer items from the ViewBag.Customers property and renders the CompanyName column value in table rows. When you run the ShowCustomers view for the first time, i.e., GET request, the request is handled by the ShowCustomers() action method whereas when you change any selection from the DropDownList the POST request is handled by the ShowCustomers(city) action method. This way, after the postback ViewBag.Customers will have only the Customer items belonging to the selected city.
Before going ahead, test the AutoPostBack functionality developed so far by selecting various city names in the DropDownList.

Implementing Partial Page AutoPostBack

As mentioned earlier, implementing partial page AutoPostBack requires some client side code. You will be using jQuery for the client side functionality. So, add a <script> reference in the ShowCustomers view as shown below :
 <script src="../../Scripts/jquery-1.4.4.js" type="text/javascript"></script>
Then add a <script> block and write a function - GetCustomers() as shown below :
<script type="text/javascript">

    function GetCustomers() {

        var success = function (results) {

            $("#customerTable").find("tr:gt(0)").remove();

            for (var i = 0; i < results.length; i++) {

                $("#customerTable").append("<tr><td>" + results[i].CompanyName + "</td></tr>");

            }

        };

        $.ajax({ url: '/home/GetCustomersByCityAJAX', 

                    type: 'POST', 

                    data: { city : $("#city").val() }, 

                    dataType: 'json', 

                    success: success 

        });

    }

</script>
Observe the GetCustomers() function carefully. It makes use of $.ajax() to call the GetCustomersByCityAJAX() action method you wrote earlier. The first parameter of the $.ajax() call is the URL to the action method in the form <controller>/<action_method>. The type parameter indicates the request type and you set it to POST. The data parameter specifies the parameter values needed while calling the GetCustomersByCityAJAX() action method. The data must be sent in JSON format. Notice the use of val() method to retrieve the DropDownList selection. The success parameter indicates a function that will be called upon successful completion of the remote method call. The success function receives the value returned by the remote method as the result parameter. The code inside the success function first removes all the rows from the customerTable and then adds rows for the newly received Customer items. Notice the use of the append() jQuery method to add a row to the table.
Once you complete the GetCustomers() method, add another DropDownList to the view as shown below:
 <%= Html.DropDownList("city2", new SelectList(ViewBag.CityNames, ViewBag.SelectedCity), new { onchange = "GetCustomers();" })%>
Notice that this time the onchange event handler points to the GetCustomers() function instead of submitting the form.
Now, run the view again and test the partial page AutoPostBack.

Summary

Many web pages require that when you change selection of a DropDownList, the page be automatically posted to the server. You can implement such an AutoPostBack in two ways - full page AutoPostBack and partial page AutoPostBack. In the former case you submit the form via client side code wired to the onchange event handler of a DropDownList. In the latter case you call an action method using jQuery $.ajax() when the onchange event is triggered.
Keywords: ASP.NET, SQL SERVER, WEB FORM, ASP.NET MVC,

About the Author

Bipin Joshi is a blogger and writes about apparently unrelated topics - Yoga & technology! A former Software Consultant by profession, Bipin has been programming since 1995 and has been working with the .NET framework ever since its inception. He has authored or co-authored half a dozen books and numerous articles on .NET technologies. He has also penned a few books on Yoga. He was a well known technology author, trainer and an active member of Microsoft developer community before he decided to take a backseat from the mainstream IT circle and dedicate himself completely to spiritual path. Having embraced Yoga way of life he now codes for fun and writes on his blogs. He can also be reached there.

Downloads

  • Code.zip
  • Không có nhận xét nào:

    Đăng nhận xét