Windows 8 - HTML 5, JavaScript & Windows Azure
Filter Weekdays from a Date Range

Filter and Display Data with ASP.NET MVC (Part 2)–Partial Views and JQuery

In the previous blog post the sample to filter and display data with Formula 1 racers filtered by the country was started with ASP.NET MVC3. The first part created the model using the ADO.NET Entity Framework to map the Racers table to the Racer type, a controller to return filtered racers, and a view to display the racers. This article extends the example by adding a country selection and using JQuery to get the racers based on the selection.

DropDownList and ViewBag

First let’s start adding a controller method to display the countries of all racers. In the previous sample data was sent from the controller to the view by passing a model to the View method. This is one way of passing data to the view. Another way that is used here, is using ViewData or ViewBag properties of the ViewPage class. ViewData is of type ViewDataDictionary and allows assigning any object by using a dictionary key. ViewBag is new with MVC 3 and uses dynamic extensions to allow writing code without using the indexer syntax. For example, instead of writing ViewData[“Countries”], ViewBag.Countries can be used.

In the sample, a SelectList is assigned to ViewBag.Countries. SelectList is used to fill HTML select elements. SelectList is a collection of SelectListItem objects and has DataTextField and DataValueField properties to define what should be displayed in the select element, and what should be used as a value of the select element. In the sample, the SelectList is filled with a string list of unique countries.

public ViewResult Index() { var countries = new SelectList( db.Racers.Select(r => r.Country).Distinct().ToList()); ViewBag.Countries = countries; return View(); }

Within the view the HTML Helper method DropDownList can be used to create a select HTML element. The method DropDownList is defined with the class SelectExtensions. SelectExtensions defines extension methods to the HtmlHelper type for ListBox and DropDownList. The first paramter used with DropDownList defines a name and id for the HTML select element and also uses ViewData with the key of the first parameter (Countries) to display these data with option elements. The second parameter defines the option that is selected by default – in case it doesn’t exist this option is added.

<legend>Racers by Country</legend> <div> @Html.DropDownList("Countries", "select a country") </div>

Running the application the select element lists countries from all racers as shown in the following figure.

image

After the country is selected, the racers of the country should be displayed.

Partial View

With the previous blog post racers have been filtered based on a country by using an URL parameter route. Instead of building the same functionality within the page that contains the DropDownList it would make sense to make that functionality reusable. With ASP.NET MVC something like user controls can be created. With ASP.NET MVC the technology to render a part of a Web page is a partial view. According to that the action method within the controller returns a PartialViewResult that is created from the PartialView method:

public PartialViewResult RacersByCountryPartial(string id) { return PartialView( db.Racers.Where(r => r.Country == id).OrderByDescending(r => r.Wins) .ThenBy(r => r.Lastname).ToList()); }

The partial view that makes use of the model is defined in the view file RacersByCountryPartial.cshml. The implementation is the same as in the previous blog post just with the difference that here’s just the HTML part defined that goes into another HTML page.

@model IEnumerable<MvcDataQuery.Content.Racer> <table> <tr> <th> Firstname </th> <th> Lastname </th> <th> Country </th> <th> Starts </th> <th> Wins </th> </tr> @foreach (var item in Model) { <tr> <td> @Html.DisplayFor(modelItem => item.Firstname) </td> <td> @Html.DisplayFor(modelItem => item.Lastname) </td> <td> @Html.DisplayFor(modelItem => item.Country) </td> <td> @Html.DisplayFor(modelItem => item.Starts) </td> <td> @Html.DisplayFor(modelItem => item.Wins) </td> </tr> } </table>

A partial view can be rendered within a page by using the method RenderPartial. This method requires the action and model with the parameters. If the page itself has a model directive, the model can be passed to the partial action using ViewData.Model.

@{ Html.RenderPartial("RacersByCountryPartial", ViewData.Model); }

With the sample the action to request the partial page should be done from the client side using JavaScript when the selection of the select element changes. This is done in the next step.

Requesting Partial Views with JQuery

JQuery scripts are included with ASP.NET MVC by default. So now we’re making use of JQuery to request the partial view from the server.

First, empty div elements are defined that will be updated by JQuery calls.

<fieldset> <legend>Racers by Country</legend> <div> @Html.DropDownList("Countries", "select a country") </div> <br /> <div id="target"> </div> <div id="log"> </div> </fieldset>

Now let’s get into scripting. On the change event of the select element that lists the countries, the racers should be requested. The event handler can only be added after the DOM of the page is loaded.

$ is a shorthand alias for the jquery function. The first selector that is used is the document itself. The ready function binds a function that is invoked as soon as DOM of the page is ready to be used. The function that is invoked as soon as DOM is loaded searches for the element with the name Countries (using #Countries in the selector) and binds a function to the change event of that element.

<script type="text/javascript"> $(document).ready(function () { $("#Countries").change(function () { }); }); </script>

The function that is bound to the change event of the select element is invoked as soon as the selection is changed. Let’s implement this function. First we need to find the selected country. The variable countrySelected gets the current selection from the select element. $(“select option:selected”) finds the option elements inside the select element that have the selected attribute set to true. Because with a multi-selection select more than one items can be selected (which is not the case here), we need to get just one. The first() function just returns one element. text() gets the text value from this element, which is the selected country. $.get() makes an HTTP GET request. The first parameter of the requires the URL to be passed. The URL is generated from the server-side method Url.Action. This method returns the relative path to the controller where the parameter of the method is appended. With this sample it’s the Home controller and thus the relative path /Home/RacersByCountryPartial. The second parameter of the get function specifies key/value pairs that are sent to the server. Here the selected country retrieved from the select element is passed. The next parameter defines a function that is invoked as soon as the result from the HTTP GET request is returned. The selector looks for the div element with the target id, then the content of the div element is updated with the data returned from the GET request.

<script type="text/javascript"> $(document).ready(function () { $("#Countries").change(function () { var countrySelected = $("select option:selected").first().text(); $.get('@Url.Action("RacersByCountryPartial")', { id: countrySelected }, function (data) { $("#target").html(data); }); }); }); </script>

Of course the HTTP GET request to the server can fail. That’s why a function is attached in case an Ajax call fails. Within this function just a message box is shown to display the error.

<script type="text/javascript"> $(document).ready(function () { $("#Countries").change(function () { $("#log").ajaxError(function (event, jqxhr, settings, exception) { alert(exception); }); var countrySelected = $("select option:selected").first().text(); $.get('@Url.Action("RacersByCountryPartial")', { id: countrySelected }, function (data) { $("#target").html(data); }); }); }); </script>
Now the sample is ready to filter and display racers.  
image

This concludes the filter and query sample with ASP.NET MVC.

Summary

With ASP.NET MVC the server-side functionality is separated into controller, view, and model. This separation makes it easy to create unit tests. This is in contrast to the technology ASP.NET Web Pages that was shown earlier. ASP.NET Web Pages makes a mix of server-side code within client-side pages. ASP.NET Web Pages an serve as a starter, then it is easy to change into ASP.NET MVC by adding models and controllers, and changing the views accordingly.

ASP.NET MVC also full control over the client writing HTML code with JavaScript and JavaScript libraries such as JQuery. HTML Helper methods make it easy to generate HTML code.

ASP.NET MVC has a big difference compared to writing Web applications with ASP.NET Web Forms. Using ASP.NET Web Forms, Web applications can be written nearly without any HTML and JavaScript code. This makes it easy if a developer is coming from writing Windows Forms applications, but looses control over data sent across the network and performance both on the client- and the server side.

ASP.NET MVC gives full control over HTML and JavaScript. JQuery makes writing scripting code easier especially if you are used to writing Lambda expressions. Functionality behind the scene is written with well known .NET technologies. The MVC pattern makes unit testing a lot easier.

Christian

CN innovation

All the articles of this ASP.NET series

More information in my workshops

Comments

Feed You can follow this conversation by subscribing to the comment feed for this post.

Quang

Great article. This is why I hate AjaxControlToolkit.

Thanks for sharing.

Quang

thin nguyen

I follow your instructions but have not been. please share your code.thanks

Naresh Kumar

I was really struggling how to perform partial refreshes, you have shown a very nice example thank you very much.

Naresh

Pieter

Very usefull and clear example, saved me a lot of time!
Thanx.

Lewis

Following your Tutorial, its exactly what I need. However struggling to get it to work. Would like some source code to be avaliable to see where it is I'm going wrong.

Thank you.

Berk

Requesting Partial Views with JQuery = Source code shared ?

ansar

sir i need source code of this tutorial
m.ansarilyas9@gmail.com

Rafael Liendo

The example is not complete. Where is "#target"?. How and where is the data show in your example. You need to put all the information

Dai

thank you very much , save my day !

The comments to this entry are closed.