This post walks you through creating a UI for paging, sorting and filtering a list of data items. It makes use of the excellent MVCContrib Grid and Pager Html UI helpers. A sample project is attached at the bottom.
Our UI will eventually look like this. The application will make use of the Northwind database.
The top portion of the page has a filter area region. The filter region is enclosed in a form tag. The select lists are wired up with jQuery to auto post back the form.
The page has a pager region at the top and bottom of the product list.
The product list has a link to display more details about a given product. The column headings are clickable for sorting and an icon shows the sort direction.A request with this UI will look similar to this : /Products?productName=chai&supplierId=29&categoryId=4&Column=CategoryName&Direction=Ascending. This request translates into a request for products that contain the text “chai” and supplierid=29 and categoryid=29. The results are sorted in ascending order by categoryname.
Strongly Typed View Models
The views are written to expect strongly typed objects. We suffix these strongly typed objects with ViewModel and will be used for passing data down to the view.
The following listing shows the ProductViewModel. This class will be used to hold information about a Product. We use attributes to specify if the property should be hidden and what its heading in the table should be. This metadata will be used by the MvcContrib Grid to render the table. Some of the properties are hidden from the UI ([ScaffoldColumn(false)) but are needed because we will be using those for filtering when writing our LINQ query.
The following diagram shows the rest of the key ViewModels in our design.
We have a container class called ProductListContainerViewModel which has nested classes.
The ProductPagedList is of type IPagination<ProductViewModel>. The MvcContrib expects the IPagination<T> interface to determine the page number and page size of the collection we are working with. You convert any IEnumerable<T> into an IPagination<T> by calling the AsPagination extension method in the MvcContrib library. It also creates a paged set of type ProductViewModel.
The ProductFilterViewModel class holds information about the different select lists and the ProductName being searched on. It also holds the state of any previously selected item in the lists and the previous search criteria (you will recall that this type of state information was stored in Viewstate when working with WebForms). With MVC there is no default state storage and so all state has to be fetched and passed back to the view.
The GridSortOptions is a type defined in the MvcContrib library and is used by the Grid to determine the current column being sorted on and the current sort direction.
The following shows the view and partial views used to render our UI. The Index view expects a Model of type ProductListContainerViewModel.
The View contains a partial view “SearchFilters” and passes it the ProductViewFilterContainer. The SearchFilter uses this Model to render all the search lists and textbox.
The partial view “Pager” uses the ProductPageList which implements the interface IPagination. The “Pager” view contains the MvcContrib Pager helper used to render the paging information. This view is repeated twice since we want the pager UI to be available at the top and bottom of the product list. The Pager partial view is located in the Shared directory so that it can be reused across Views.
The partial view “SearchResults” uses the ProductListContainer model. This partial view contains the MvcContrib Grid which needs both the ProdctPagedList and GridSortOptions to render itself.
The Controller Action
The application receives this GET request and maps it to the Index method of the ProductController.
Within the action we create an IQueryable<ProductViewModel> by calling the GetProductsProjected() method.
The supplier, category and productname filters are applied to this IQueryable if any are present in the request. The ProductPagedList class is created by applying a sort order and calling the AsPagination method. Finally, the ProductListContainerViewModel class is created and returned to the view.
You have seen how to use strongly typed views with the MvcContrib Grid and Pager to render a clean lightweight UI with strongly typed views. You also saw how to use partial views to get data from the strongly typed model passed to it from the parent view. The code also shows you how to use jQuery to auto post back.
The nice thing about the MvcContrib Pager and Grid is that it is aware of the original query string and keeps it intact when creating links for sorting and paging.
The sample is attached below. Don’t forget to change your connection string to point to the server containing the Northwind database.
- Creating an ASP.NET report using Visual Studio 2010
- Running ASP.NET Webforms and ASP.NET MVC side by side
- ActionResult types in MVC 2
- Code snippets for ASP.NET MVC2 in VS 2010
- Securing an ASP.NET MVC 2 Application
My name is Kobayashi. I work for Keyser Soze.