(Homework) MVC Pagination Help
I'm attempting to put together a very simple application using ASP.NET MVC that shows news articles and paginates them. I'm sort of half-way there but need some help sorting out the pagination and getting it to work with the search query.
Here is my HomeController:
public ActionResult Index(String query, int? page)
{
// limit the number of articles per page
const int pageSize = 4;
// build the query
var ArticleQuery = from a in _db.ArticleSet select a;
// check if their is a query
if (!string.IsNullOrEmpty(query))
{
ArticleQuery = ArticleQuery.Where(a => a.headline.Contains(query));
}
// orders the articles
var OrderedArticles = ArticleQuery.OrderByDescending(a => a.posted);
// takes the ordered articles and paginates them
//var paginatedArticles = new PaginatedList(OrderedArticles.Skip((page ?? 0) * pageSize).Take(pageSize), page ?? 0, pageSize);
var paginatedArticles = new PaginatedList<Article>(OrderedArticles, page ?? 0, pageSize);
// return the paginated articles to the view
return View(paginatedArticles);
}
The idea is that the Controller shows 4 items per page will order them by date. Here is the View I have for the Index method:
<ul id="pagination">
<% if (Model.PreviousPage) { %>
<li><%= Html.ActionLink("<< First Page", "Index")%></li>
<li><%= Html.ActionLink("<< Previous Page", "Index", new { page=(Model.PageIndex-1) }) %></li>
<% } %>
<% if (Model.NextPage) { %>
<li><%= Html.ActionLink("Next Page >>", "Index", new { page = (Model.PageIndex + 1) })%></li>
<li><%= Html.ActionLink("Last Page >>", "Index", new { page = (Model.TotalPages - 1) })%></li>
<% } %>
</ul>
The idea is that these two pagination links will only show if the conditions are true.
Finally here is the PaginatedList class for the pager:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
namespace NewsApp.Models
{
public class PaginatedList<T> : List<T>
{
public int PageIndex { get; private set; }
public int PageSize { get; private set; }
public int TotalCount { get; private set; }
public int TotalPages { get; private set; }
public PaginatedList(IQueryable<T> source, int pageIndex, int pageSize)
{
PageIndex = pageIndex;
PageSize = pageSize;
TotalCount = source.Count();
TotalPages = (int)Math.Ceiling(TotalCount / (double)PageSize);
this.AddRange(source.Skip(PageIndex * PageSize).Take(PageSize));
}
public bool HasPreviousPage
{
get
{
return (PageIndex > 0);
}
}
public bool HasNextPage
{
get
开发者_运维技巧 {
return (PageIndex + 1 < TotalPages);
}
}
}
NOTE: I' don't want to use any 3rd party components like MVCContrib etc as this is for a University assignment so would defeat the purpose.
The pagination works fine now but when I do a search and have e.g. /?query=test I want to be able to page the results, at the moment they get lost :/
Thanks.
You didn't cite what you're actual error is, but I think I see what's wrong:
These two lines will return your an IEnumerable containing your results.
var paginatedArticles = OrderedArticles.Skip((page ?? 0) * pageSize).Take(pageSize).ToList();
return View(paginatedArticles);
However, based on your view and the helper class you posted, you're view is expecting PaginatedList
object as its Model.
If that's the case, I'd do the following (updated):
var paginatedArticles = new PaginatedList( OrderedArticles, page ?? 0, pageSize );
return View(paginatedArticles);
And then your view should have the proper model being returned to it.
That said: I don't know why you aren't using a repository layer, but unless your app is only a single page it is almost always a good idea to have one in place.
Update --here's what I think the full controller logic should be:
public ActionResult Index(String query, int? page)
{
const int pageSize = 4;
var ArticleQuery = from m in _db.ArticleSet select m;
// Searching
if (!string.IsNullOrEmpty(query))
{
ArticleQuery = ArticleQuery.Where(m => m.headline.Contains(query));
}
var OrderedArticles = ArticleQuery.OrderByDescending(m => m.posted);
var paginatedArticles = new PaginatedList( OrderedArticles, page ?? 0, pageSize );
// this will now be of type paginatedList. this class handles all of the paging for you, so no need to do that ahead of time
return View(paginatedArticles);
}
In this case, PaginatedList is NOT a helper --its a full on class that needs to be created and passed to your model. A helper in the strict definition of the word is done much differently and probably wouldn't work in your case here.
精彩评论