MvcContrib grid paging and searching in Asp.NET MVC3
Introduction
This article shows you how to implement MvcContrib grid paging,filtering and preserving search url in Asp.NET MVC3.
Background
MvcContrib grid provides nice paging interface with column ordering function. In real world, we need to aggregate complex ViewModels to present multiple models to grid view. In most of case, we also should provide multiple searching filters and keywords with 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
Summary
I added some codes and classes to the original source to simplify implementation as follows:
- PagedViewModel<T> contains ViewModel,IFilterViewItem collection and paging information.
- IFilterViewItem, FilterViewItem and SelectListFilterViewItem for simple query filter setting.
- Preserving the query url between list page and view page.
Businss Layer
Let's use the music store database of http://chinookdatabase.codeplex.com/ 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 { [DisplayName("ID")] public int AlbumId { get; set; } [ScaffoldColumn(false)] public int? GenreId { get; set; } [DisplayName("Genre")] public string Genre { get; set; } [ScaffoldColumn(false)] public int? ArtistId { get; set; } [DisplayName("Artist")] public string Artist { get; set; } [ScaffoldColumn(false)] public string AlbumTitle { get; set; } [DisplayName("Price")] [DisplayFormat(DataFormatString = "{0:c}")] public decimal AlbumPrice { get; set; } } }
Let's build our main business service methods. 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() { _context.SaveChanges(); } } }
PagedViewModel<T> and IFilterViewItem<T>
PagedViewModel<T> is generic container holding all data for grid presentation including search filters. There are also two types of IFilterViewItem<TModel> implementations. FilterViewItem<T> is for saving simple filter data like search keyword and SelectListFilterViewItem is for saving SelectList object.
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") .Setup(); return View(pagedViewModel); } ... } }
Listing Razor View Page for MvcContrib Grid
Let's make List View Page. We can easily fill two dropdownlist without any additional code from PagedViewModel<T>. Also, We add link using Html.ActionQueryLink helper method to keep query string like "/Album/Details/420?albumTitle=Ro&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" })) { <label> Title @Html.TextBox("albumTitle") Genre @Html.DropDownList("genreId", "-- Select All --") </label> <label> Artist @Html.DropDownList("artistId", "-- Select All --") <input class="button" value="Search" type="submit" /> </label> } @{Html.RenderPartial("Pager", Model.PagedList);} @Html.Grid(Model.PagedList).AutoGenerateColumns().Columns(column =>
Let's see SearchBox with title keyword, Genre&Album Dropdownlist. The contrib Grid provides Colum filtering and paging UI.
We can back to 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> <p> @Html.ActionLink("Back to List", "Index", ViewBag.RouteDicForList as RouteValueDictionary) </p>
Conclusion
MvcContrib Grid is nice web grid component for MVC3 framework. We can use great paging,filtering,ordering grid functions easily.
Reference
- Raj Kaimal : ASP.NET MVC Paging/Sorting/Filtering using the MVCContrib Grid and Pager
- MVC Contrib Homepage
- Chinook Sample Database
- Css and design : Styleshout.com
发表评论
uB4Ngb Wonderful article! We will be linking to this great article on our site. Keep up the good writing.
Interpult Studio
Bxgpox Thanks a lot for the post. Fantastic.
v4QduN Appreciate you sharing, great article.Really thank you! Really Great.
Прогоняю лицензионным Хрумером XRumer 7.0.12 по блогам, форумам, гостевым книгам + сбор индивидуальных баз!
стучим в аську 623935432
ОТВЕЧАЮ ВСЕМ, если я Вам не ответил - СТУКНИТЕ ЕЩЕ РАЗОК :)
------------------------------------------------------------------------------------------------------------
ПО ВСЕМ ВОПРОСАМ В АСЬКУ, ВАРИАНТОВ РАССЫЛОК МНОГО И НА КАЖДЫЙ ВАРИАНТ ИЛИ КОМБИНАЦИЮ СВОЯ ЦЕНА И СКИДКА :)
ПРИМЕРНЫЕ ЦЕНЫ:
Все цены за объем в 60к (баз много ru и en)
1.Прямой - 20вмз
2.Агрессивный - 25вмз
3.Профили - 10вмз
4.Рефспам - 7вмз
ПРИ БОЛЬШИХ ОБЪЕМАХ ИЛИ КОМПЛЕКСНОМ ЗАКАЗЕ СКИДКИ ДО 50% :)
------------------------------------------------------------------------------------------------------------
ОЧЕНЬ прошу не задавать вопросов: "а сколько уников будет?" "а сколько я заработаю на выхлопе?" и т.д и т.п ВСЕ СУГУБО ИНДИВИДУАЛЬНО и зависит от КУЧИ факторов начиная от конкуренции в данном сегменте вашей тематики до актуальности вашей темы и умения составить проект!
************************************************** *********************************
Варианты прогона:
1. Прямой постинг
Это стандартный метод: Ваш текст рассылается по форумам или гостевым книгам или блогам.
2. Агрессивный постинг
Тоже самое что и Прямой постинг, только топик создаётся не в одном, а сразу во всех разделах форума (по возможности).
3. По профилям
Регистрируются профили в которых в поле Домашняя страница проставляется ваша ссылка, так сказать "вечные" бэклинки.
4. Рефспам
Метод заключается в отправке реф.запросов страницам сайта, с указанием в запросе referer="ваш_сайт" , вследствие чего на сайтах, на спец.странице отображается адрес Вашего сайта. Основная направленность - на поисковые системы.
стучим в аську 623935432Прогоняю лицензионным Хрумером XRumer 7.0.12 по блогам, форумам, гостевым книгам + сбор индивидуальных баз!
стучим в аську 623935432
ОТВЕЧАЮ ВСЕМ, если я Вам не ответил - СТУКНИТЕ ЕЩЕ РАЗОК :)
------------------------------------------------------------------------------------------------------------
ПО ВСЕМ ВОПРОСАМ В АСЬКУ, ВАРИАНТОВ РАССЫЛОК МНОГО И НА КАЖДЫЙ ВАРИАНТ ИЛИ КОМБИНАЦИЮ СВОЯ ЦЕНА И СКИДКА :)
ПРИМЕРНЫЕ ЦЕНЫ:
Все цены за объем в 60к (баз много ru и en)
1.Прямой - 20вмз
2.Агрессивный - 25вмз
3.Профили - 10вмз
4.Рефспам - 7вмз
ПРИ БОЛЬШИХ ОБЪЕМАХ ИЛИ КОМПЛЕКСНОМ ЗАКАЗЕ СКИДКИ ДО 50% :)
------------------------------------------------------------------------------------------------------------
ОЧЕНЬ прошу не задавать вопросов: "а сколько уников будет?" "а сколько я заработаю на выхлопе?" и т.д и т.п ВСЕ СУГУБО ИНДИВИДУАЛЬНО и зависит от КУЧИ факторов начиная от конкуренции в данном сегменте вашей тематики до актуальности вашей темы и умения составить проект!
************************************************** *********************************
Варианты прогона:
1. Прямой постинг
Это стандартный метод: Ваш текст рассылается по форумам или гостевым книгам или блогам.
2. Агрессивный постинг
Тоже самое что и Прямой постинг, только топик создаётся не в одном, а сразу во всех разделах форума (по возможности).
3. По профилям
Регистрируются профили в которых в поле Домашняя страница проставляется ваша ссылка, так сказать "вечные" бэклинки.
4. Рефспам
Метод заключается в отправке реф.запросов страницам сайта, с указанием в запросе referer="ваш_сайт" , вследствие чего на сайтах, на спец.странице отображается адрес Вашего сайта. Основная направленность - на поисковые системы.
стучим в аську 623935432Прогоняю лицензионным Хрумером XRumer 7.0.12 по блогам, форумам, гостевым книгам + сбор индивидуальных баз!
стучим в аську 623935432
ОТВЕЧАЮ ВСЕМ, если я Вам не ответил - СТУКНИТЕ ЕЩЕ РАЗОК :)
------------------------------------------------------------------------------------------------------------
ПО ВСЕМ ВОПРОСАМ В АСЬКУ, ВАРИАНТОВ РАССЫЛОК МНОГО И НА КАЖДЫЙ ВАРИАНТ ИЛИ КОМБИНАЦИЮ СВОЯ ЦЕНА И СКИДКА :)
ПРИМЕРНЫЕ ЦЕНЫ:
Все цены за объем в 30к (баз много ru и en)
1.Прямой - 20вмз
2.Агрессивный - 25вмз
3.Профили - 20вмз
4.Рефспам - 7вмз
ПРИ БОЛЬШИХ ОБЪЕМАХ ИЛИ КОМПЛЕКСНОМ ЗАКАЗЕ СКИДКИ ДО 50% :)
------------------------------------------------------------------------------------------------------------
ОЧЕНЬ прошу не задавать вопросов: "а сколько уников будет?" "а сколько я заработаю на выхлопе?" и т.д и т.п ВСЕ СУГУБО ИНДИВИДУАЛЬНО и зависит от КУЧИ факторов начиная от конкуренции в данном сегменте вашей тематики до актуальности вашей темы и умения составить проект!
************************************************** *********************************
Варианты прогона:
1. Прямой постинг
Это стандартный метод: Ваш текст рассылается по форумам или гостевым книгам или блогам.
2. Агрессивный постинг
Тоже самое что и Прямой постинг, только топик создаётся не в одном, а сразу во всех разделах форума (по возможности).
3. По профилям
Регистрируются профили в которых в поле Домашняя страница проставляется ваша ссылка, так сказать "вечные" бэклинки.
4. Рефспам
Метод заключается в отправке реф.запросов страницам сайта, с указанием в запросе referer="ваш_сайт" , вследствие чего на сайтах, на спец.странице отображается адрес Вашего сайта. Основная направленность - на поисковые системы.
стучим в аську 623935432Предлогаю прогон по 1200 трастовым профилям
(профили с тиц выше 10)
Цена прогона: 10$
ICQ 623935432Предлагаю рассылку по форумам,блогам,гостевым книгам,каталогам,
доскам,специальным движкам.
Рост бэклинков,PR,трафик.
Цены от 10$.
ICQ 623935432是的......设计是清楚的旅客将不得不改变:)
墨绿色的颜色会伏贴XDАптека: виагра купить в ростове, левитра, левитра варденафил, сиалис виагра отзывы, препарат виагра применение, дженерик сиалис софт купить, купить виагра петербург, виагра таблетки цена, лечение сиалисом, сиалис софт, левитра фото.
Магазин обуви: интернет магазин женской обуви недорого Liska (Лиска), гост обувь женская Liska (Лиска), женская обувь лето 2011 Liska (Лиска), магазин женской и мужской обуви Liska (Лиска), женская обувь испания Liska (Лиска).
Магазин обуви: adidas зимняя обувь женская Liska (Лиска), женская обувь осень 2010 Liska (Лиска), зимняя обувь женская 2010 Liska (Лиска), скидки женская обувь зимняя Liska (Лиска), купить женскую обувь в петербурге Liska (Лиска).
Магазин обуви: фирменные магазины женской обуви Liska (Лиска), skechers женская обувь Liska (Лиска), смотреть женскую обувь Liska (Лиска), интернет магазин женской обуви 2010 Liska (Лиска), интернет магазин женской резиновой обуви Liska (Лиска).