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:
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.
Once created, your Customer entity class
should look like this:
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.
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.
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.
Không có nhận xét nào:
Đăng nhận xét