Click here to Skip to main content
13,197,342 members (29,221 online)
Click here to Skip to main content
Add your own
alternative version


107 bookmarked
Posted 20 Mar 2011

MvcContrib Grid Paging and Searching in ASP.NET MVC3

, 4 May 2011
Rate this:
Please Sign up or sign in to vote.
How to implement MvcContrib Grid paging, sorting, filtering and preserving query URL in ASP.NET MVC3


This article shows you how to implement MvcContrib grid paging, filtering and preserving search URL in ASP.NET MVC3.


MvcContrib grid provides nice paging interface with column ordering. In the real world, we need to aggregate complex ViewModels to present grid view. We should also provide multiple searching filters and keywords to the grid view.

So, I implemented clean PagedViewModel<T> class to make MvcContrib Grid paging and filtering simple in ASP.NET MVC3, based on this nice article.

Using the Code


I added some code and classes to the original source to simplify implementation as follows:

  • PagedViewModel<T> containing IPagenation<T>, AddFilter methods and sorting/paging information
  • Preserving the query URL between list page and view page

Business Layer

Let's use the music store database of for our AlbumServie. (*I attached the mdf with basic connection string in web.config in our MVC project.)

Let's add MVCMusicStoreDB EF4 model including Album, Genre and Artist tables. We can see the basic entity diagram.

The AlbumViewModel class is the composite ViewModel class of Album, Genre and Artist entities. The MvcContrib Grid uses those Display* and ScaffoldColumn attributes in the AutoGenerateColumns() function.

using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
namespace MvcMusicStore.Models
    public class AlbumViewModel
        public int AlbumId { get; set; }
        public int? GenreId { get; set; }
        public string Genre { get; set; }
        public int? ArtistId { get; set; }
        public string Artist { get; set; }
        public string AlbumTitle { get; set; }
        [DisplayFormat(DataFormatString = "{0:c}")] 
        public decimal AlbumPrice { get; set; }

Let's build our main business service methods. The first step is adding some basic reading methods in AlbumService. We don't implement CUD methods and any UoW or Repository layer for simple & quick implementation.

namespace MvcMusicStore.Models
    public class AlbumService
        private MvcMusicStoreEntities _context;
        public AlbumService()
            _context = new MvcMusicStoreEntities();
        public IQueryable<AlbumViewModel> GetAlbumsView()
            var query = from a in GetAlbums()
                        select new AlbumViewModel
                            AlbumId = a.AlbumId,
                            GenreId = a.GenreId,
                            Genre = a.Genre.Name,
                            ArtistId = a.ArtistId,
                            Artist = a.Artist.Name,
                            AlbumTitle = a.Title,
                            AlbumPrice = a.Price
            return query;
        public AlbumViewModel FindAlbumView(int albumId)
            return GetAlbumsView().Where(a => a.AlbumId == albumId).Single();
        public IQueryable<Album> GetAlbums()
            return _context.Albums;
        public IQueryable<Genre> GetGenres()
            return _context.Genres;
        public IQueryable<Artist> GetArtists()
            return _context.Artists;
        public void Save()


PagedViewModel<T> is the generic container holding all data for grid presentation including search filters. There are also several AddFilter implementations that register simple filters like search keyword and SelectListFilterViewItem is for saving SelectList object with adding viewdata dictionay.

To support fluent filter setting function to the PagedViewModel<T>, we should implement AddFilter and Setup methods.

namespace MvcMusicStore.Models
    public class PagedViewModel<T>
    {   ...
        public PagedViewModel<T> AddFilter(Expression<Func<T, bool>> predicate)
            Query = Query.Where(predicate);
            return this;
        public PagedViewModel<T> AddFilter<TValue>
	(string key, TValue value, Expression<Func<T, bool>> predicate)
            ProcessQuery(value, predicate);
            ViewData[key] = value;
            return this;
        public PagedViewModel<T> AddFilter<TValue>
	(string keyField, object value, Expression<Func<T, bool>> predicate,
            IQueryable<TValue> query, string textField)
            ProcessQuery(value, predicate);
            var selectList = query.ToSelectList(keyField, textField, value);
            ViewData[keyField] = selectList;
            return this;
        public PagedViewModel<T> Setup()
            if (string.IsNullOrWhiteSpace(GridSortOptions.Column))
                GridSortOptions.Column = DefaultSortColumn;
            PagedList = Query.OrderBy
		(GridSortOptions.Column, GridSortOptions.Direction)
                .AsPagination(Page ?? 1, PageSize ?? 10);
            return this;
        private void ProcessQuery<TValue>
		(TValue value, Expression<Func<T, bool>> predicate)
            if (value == null) return;
            if (typeof(TValue) == typeof(string))
                if (string.IsNullOrWhiteSpace(value as string)) return;
            Query = Query.Where(predicate);

Listing Action Method in Controller

Let's make a listing method of AlbumController with searching filters, ordering and paging in our AlbumController. We can add fluently query filters to the filter pipeline of PagedViewModel.

namespace MvcMusicStore.Controllers 
    public class AlbumController : Controller 
        private AlbumService _service; 
        public AlbumController() 
            _service = new AlbumService(); 
        public ActionResult Index(string albumTitle, 
	int? genreId, int? artistId, GridSortOptions gridSortOptions, int? page) 
            var pagedViewModel = new PagedViewModel<AlbumViewModel> 
                ViewData = ViewData, 
                Query = _service.GetAlbumsView(), 
                GridSortOptions = gridSortOptions, 
                DefaultSortColumn = "AlbumId", 
                Page = page, 
            .AddFilter("albumTitle", albumTitle, 
			a => a.AlbumTitle.Contains(albumTitle)) 
            .AddFilter("genreId", genreId, 
		a => a.GenreId == genreId, _service.GetGenres(), "Name") 
            .AddFilter("artistId", artistId, 
		a => a.ArtistId == artistId, _service.GetArtists(), "Name") 
            return View(pagedViewModel); 

Listing Razor View Page for MvcContrib Grid

Let's make List View Page. We can easily fill two dropdownlists without any additional code from PagedViewModel<T>. Also, we add a link using Html.ActionQueryLink helper method to keep query string like "/Album/Details/420?albumTitle=Ro&amp;genreId=1".

@using MvcMusicStore.Common 
@using MvcMusicStore.Models; 
@using MvcContrib.UI.Grid; 
@model PagedViewModel<AlbumViewModel> 
    ViewBag.Title = "Album List"; 
<h2>Album List</h2> 
@using (Html.BeginForm("Index", "Album", 
	FormMethod.Get, new { id = "albumSearch" })) 
Title   @Html.TextBox("albumTitle") 
  Genre @Html.DropDownList("genreId", "-- Select All --") 
Artist @Html.DropDownList("artistId", "-- Select All --") 
  <input class="button" value="Search" type="submit" /> 
@{Html.RenderPartial("Pager", Model.PagedList);} 
column =) {column.For(x =) Html.ActionQueryLink(x.AlbumTitle, "Details", 
new { id = x.AlbumId })).Named("AlbumTitle").InsertAt(2);
}).Sort(Model.GridSortOptions).Attributes(@class =) "grid-style")

Let's see SearchBox with title keyword, Genre & Album Dropdownlist. The contrib Grid provides Column filtering and paging UI.

We can go back to the List page with preserved query option from Details page. Let's add a snippet to save routing URL to ViewBag by using added ToRouteDic extension method.

namespace MvcMusicStore.Controllers
    public class AlbumController : Controller
    {   ...
        public ActionResult Details(int id)
            var viewModel = _service.FindAlbumView(id);
            ViewBag.RouteDicForList = Request.QueryString.ToRouteDic();
            return View(viewModel);

Let's restore the ViewBag data to restore the query URL in Details Viewpage.

@model MvcMusicStore.Models.AlbumViewModel
    ViewBag.Title = "Details";
<h2>Album Details - @Model.AlbumTitle</h2>
    @Html.ActionLink("Back to List", "Index", 
    ViewBag.RouteDicForList as RouteValueDictionary)


MvcContrib Grid is a nice web grid component for MVC3 framework. We can use great paging, filtering, ordering grid functions easily.



This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Sangsu Park 99
Software Developer (Senior)
Australia Australia
No Biography provided

You may also be interested in...

Comments and Discussions

QuestionPagedList Pin
countrydawgg27-Jan-15 11:56
membercountrydawgg27-Jan-15 11:56 
GeneralMy vote of 5 Pin
Armando Airo'10-Apr-13 6:07
memberArmando Airo'10-Apr-13 6:07 
QuestionAjax pager Pin
Lluthus14-Mar-13 4:05
memberLluthus14-Mar-13 4:05 
GeneralMy vote of 5 Pin
ab_thai15-Jan-13 17:05
memberab_thai15-Jan-13 17:05 
QuestionGet duplicate Search form after post Pin
khanhqhoang30-Oct-12 12:20
memberkhanhqhoang30-Oct-12 12:20 
GeneralMy vote of 5 Pin
pablopecora9-Aug-12 19:55
memberpablopecora9-Aug-12 19:55 
SuggestionDo you have the code for add/update/delete? Pin
gogsthecoder19-Jul-12 3:58
membergogsthecoder19-Jul-12 3:58 
QuestionMy vote is 5 Pin
Z@clarco17-Jul-12 23:20
memberZ@clarco17-Jul-12 23:20 
GeneralRe: My vote is 5 Pin
Sangsu Park 9918-Jul-12 0:25
memberSangsu Park 9918-Jul-12 0:25 
QuestionAnswers to some questions, over this example, on demand, custom sorting and paging Pin
Andrés Meza21-May-12 17:46
memberAndrés Meza21-May-12 17:46 
QuestionMy veto is 0 Pin
Delphy9-Apr-12 0:25
memberDelphy9-Apr-12 0:25 
AnswerRe: My veto is 0 Pin
Nabin Kumar Jha11-May-12 0:40
memberNabin Kumar Jha11-May-12 0:40 
Questionerror CS0433 about ModelClientValidationRule in Models\AccountModels.cs(242,43) Pin
sheir23-Mar-12 8:14
membersheir23-Mar-12 8:14 
QuestionPagination issue Pin
Dimitri Backaert23-Mar-12 5:06
memberDimitri Backaert23-Mar-12 5:06 
GeneralMy vote of 5 Pin
kishor Shinde23-Feb-12 20:13
memberkishor Shinde23-Feb-12 20:13 
QuestionCreating a View Pin
Member 866805523-Feb-12 19:43
memberMember 866805523-Feb-12 19:43 
QuestionAwesome Article Pin
zyck18-Feb-12 20:22
memberzyck18-Feb-12 20:22 
AnswerRe: Awesome Article Pin
Sangsu Park 9923-Feb-12 7:37
memberSangsu Park 9923-Feb-12 7:37 
QuestionGood example, but how can I add "Create New", "Edit" and "Delete" functions? Pin
peter cong18-Feb-12 4:29
memberpeter cong18-Feb-12 4:29 
AnswerRe: Good example, but how can I add "Create New", "Edit" and "Delete" functions? Pin
Sangsu Park 9923-Feb-12 7:36
memberSangsu Park 9923-Feb-12 7:36 
GeneralGreate work Pin
Dhol Gaurav5-Jan-12 8:11
memberDhol Gaurav5-Jan-12 8:11 
GeneralRe: Greate work Pin
Sangsu Park 995-Jan-12 12:46
memberSangsu Park 995-Jan-12 12:46 
Questionit has problem when i use filter and paging together Pin
funlive14-Aug-11 0:12
memberfunlive14-Aug-11 0:12 
AnswerRe: it has problem when i use filter and paging together Pin
Sangsu Park 9914-Aug-11 1:44
memberSangsu Park 9914-Aug-11 1:44 
GeneralRe: it has problem when i use filter and paging together Pin
funlive14-Aug-11 4:18
memberfunlive14-Aug-11 4:18 
GeneralRe: it has problem when i use filter and paging together Pin
Sangsu Park 9914-Aug-11 14:23
memberSangsu Park 9914-Aug-11 14:23 
QuestionSorting based on two columns Pin
danishdudeous8-Aug-11 12:05
memberdanishdudeous8-Aug-11 12:05 
AnswerRe: Sorting based on two columns Pin
Sangsu Park 998-Aug-11 14:40
memberSangsu Park 998-Aug-11 14:40 
GeneralRe: Sorting based on two columns Pin
danishdudeous9-Aug-11 10:23
memberdanishdudeous9-Aug-11 10:23 
GeneralNice! Pin
danishdudeous1-Aug-11 1:58
memberdanishdudeous1-Aug-11 1:58 
GeneralRe: Nice! Pin
Sangsu Park 991-Aug-11 3:19
memberSangsu Park 991-Aug-11 3:19 
GeneralMy vote of 4 Pin
zvin27-May-11 6:48
memberzvin27-May-11 6:48 
GeneralRe: My vote of 4 Pin
Sangsu Park 9927-May-11 14:04
memberSangsu Park 9927-May-11 14:04 
GeneralMy vote of 5 Pin
blink3ro23-May-11 4:24
memberblink3ro23-May-11 4:24 
GeneralRe: My vote of 5 Pin
Sangsu Park 9923-May-11 12:47
memberSangsu Park 9923-May-11 12:47 
GeneralHelp with AddFilter() [modified] Pin
MarkBuckley25-Apr-11 6:12
memberMarkBuckley25-Apr-11 6:12 
GeneralRe: Help with AddFilter() Pin
Sangsu Park 9925-Apr-11 13:08
memberSangsu Park 9925-Apr-11 13:08 
GeneralRe: Help with AddFilter() Pin
MarkBuckley26-Apr-11 3:19
memberMarkBuckley26-Apr-11 3:19 
GeneralMy vote of 5 Pin
Monjurul Habib1-Apr-11 8:22
memberMonjurul Habib1-Apr-11 8:22 
GeneralRe: My vote of 5 Pin
Sangsu Park 991-Apr-11 14:06
memberSangsu Park 991-Apr-11 14:06 
GeneralMy vote of 5 Pin
Kenny Nguyen Xuan Vu26-Mar-11 10:11
memberKenny Nguyen Xuan Vu26-Mar-11 10:11 
GeneralRe: My vote of 5 Pin
Sangsu Park 9926-Mar-11 19:56
memberSangsu Park 9926-Mar-11 19:56 
GeneralVery Usefull Pin
Dejan Petrovic25-Mar-11 3:42
memberDejan Petrovic25-Mar-11 3:42 
GeneralRe: Very Usefull Pin
Sangsu Park 9925-Mar-11 10:29
memberSangsu Park 9925-Mar-11 10:29 
QuestionHow can I apply this to repository pattern with DDD? Pin
mixmasterxp23-Mar-11 17:14
membermixmasterxp23-Mar-11 17:14 
AnswerRe: How can I apply this to repository pattern with DDD? Pin
Sangsu Park 9923-Mar-11 19:17
memberSangsu Park 9923-Mar-11 19:17 
GeneralGood post! Pin
Wesley Hammett21-Mar-11 11:25
memberWesley Hammett21-Mar-11 11:25 
GeneralRe: Good post! Pin
Sangsu Park 9925-Mar-11 10:30
memberSangsu Park 9925-Mar-11 10:30 
GeneralRe: Good post! Pin
strange_engine11-Dec-11 11:36
memberstrange_engine11-Dec-11 11:36 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.171020.1 | Last Updated 4 May 2011
Article Copyright 2011 by Sangsu Park 99
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid