Reputation: 28853
I have the following Index method on my app that shows a bunch of articles:
public ActionResult Index(String query)
{
var ArticleQuery = from m in _db.ArticleSet select m;
if (!string.IsNullOrEmpty(query))
{
ArticleQuery = ArticleQuery.Where(m => m.headline.Contains(query));
}
//ArticleQuery = ArticleQuery.OrderBy(m.posted descending);
return View(ArticleQuery.ToList());
}
It also doubles as a search mechanism by grabbing a query string if it exists.
Problem 1.) The OrderBy does not work, what do I need to change it to get it to show the results by posted date in descending order.
Problem 2.) I am going to adding a VERY SIMPLE pagination, and therefore only want to show 4 results per page. How would I be best going about this? Thanks
EDIT: In addition to problem 2, I'm looking for a simple Helper class solution to implement said pagination into my current code. This ones looks very good (http://weblogs.asp.net/andrewrea/archive/2008/07/01/asp-net-mvc-quot-pager-quot-html-helper.aspx), but how would I implement it into my application. Thanks.
Upvotes: 0
Views: 643
Reputation: 26792
EDIT: it doesn't get much easier using MvcContrib
1/ create your queryable source
public ActionResult Index(String query, int? page)
{
var pagesize = 4; // can also be a parameter and/or a configuration setting
var ArticleQuery = from m in _db.ArticleSet select m;
if (!string.IsNullOrEmpty(query))
{
ArticleQuery = ArticleQuery.Where(m => m.headline.Contains(query));
}
ArticleQuery = ArticleQuery.OrderByDescending(m => m.posted);
return View(ArticleQuery.AsPagination(page, pageSize));
}
2/ in your view, you can use the MvcContrib pager helper method like so:
<%= Html.Pager((IPagination)Model)%>
This will output a nice pager control.
Here's another explanation, which also uses the MvcContrib grid control (not required): http://davidhayden.com/blog/dave/archive/2009/06/25/mvccontribgridpagerhelpers.aspx
Upvotes: 2
Reputation: 43114
You'd need to restructure as follows (assuming page 0 is the first page):
public ActionResult Index(String query, int page)
{
var ArticleQuery = (from m in _db.ArticleSet select m);
if (!string.IsNullOrEmpty(query))
{
ArticleQuery = ArticleQuery.Where(m => m.headline.Contains(query));
}
ArticleQuery = ArticleQuery.Skip(page*4).Take(4).OrderByDescending(m => m.posted);
return View(ArticleQuery.ToList());
}
There are plenty of pagination solutions out there, not one that I'd recommend above any other. The code above demonstrates a backend implementation that will page, you'd still have to present the pager, etc.
Upvotes: 1
Reputation: 22485
Cameron,
I'm hoping an example by way of a link to a download will help you in this case. I made this little app for someone else on SO to help with a similar issue. Basically, it shows how to create an IPagedList interface.
i.e
public interface IPagedList
{
int PageIndex { get; set; }
int PageSize { get; set; }
int TotalPages { get; set; }
}
You then create a concrete class and populate it via your querystring params (including OrderBy etc, etc).
something like this:
public class Test
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int SerialNumber { get; set; }
}
public class TestCollection : IPagedList
{
public IList<Test> TestList { get; set; }
// purely for test purposes
public int PageIndex{ get; set; }
public int PageSize { get; set; }
public int TotalPages{ get; set; }
public TestCollection()
{
TestList = new List<Test>();
}
}
and here's how it kinda looks:
You can grab it here:
http://gatehousemusic.com/downloads/MvcApplication2.zip
have fun..
Upvotes: 0
Reputation: 1022
I am answering this from the top of my head so please check this answer is correct.
Problem 1.) That doesn't work because you are assigning an IOrderedEnumerable to an IEnumerable. ArticleQuery type should be IEnumerable.
You should change "var ArticleQuery" to "IOrderedEnumerable ArticleQuery". And this should work. If this is not the case since anyway you are converting it to List afterwards just put the ToList() before ordering it and use a separate List object.
Problem 2.) You would need something like this (untested):
int PageSize = 4;
public ActionResult Index(String query, int page)
{
IOrderedEnumerable ArticleQuery = (from m in _db.ArticleSet select m);
if (!string.IsNullOrEmpty(query))
{
ArticleQuery = ArticleQuery.Where(m => m.headline.Contains(query));
}
ArticleQuery = ArticleQuery.Skip(PageSize * (page - 1)).Take(PageSize).OrderBy(m.posted descending);
return View(ArticleQuery.ToList());
}
For the addition to problem 2 I don't know what you mean exactly please explain more in details. But in general I don't think you need an Helper class for a pagination solution.
Upvotes: 0
Reputation: 2385
(and part of .2)
return View(ArticleQuery.OrderByDecending(a => a.posted).Take(4).ToList());
Change your action (this is just going to get you started, not the best answer)
a
public ActionResult Index(string query, int page)
{
var ArticleQuery = from m in _db.ArticleSet select m;
if (!string.IsNullOrEmpty(query))
{
ArticleQuery = ArticleQuery.Where(m => m.headline.Contains(query));
}
return View(ArticleQuery.OrderByDecending(a => a.posted).Skip(page * 4).Take(4).ToList());
}
Upvotes: 0
Reputation: 2552
You can add the orderby to your original query, and the Top 4 can be done with .Take([number])
public ActionResult Index(String query)
{
var ArticleQuery = from m in _db.ArticleSet orderby posted descending select m;
if (!string.IsNullOrEmpty(query))
{
ArticleQuery = ArticleQuery.Where(m => m.headline.Contains(query));
}
return View(ArticleQuery.Take(4).ToList());
}
Upvotes: 0
Reputation: 5779
Problem #1: The OrderBy (and OrderByDescending, which I think is what you want) methods require you to pass a function to specify how to perform the ordering. Most people choose to use a lambda expression to do this:
ArticleQuery = ArticleQuery.OrderByDescending(m => m.posted);
See the MSDN page for more details.
Problem #2: You'll need to change your action method to accept page number and page size parameters, then pass these from your view. On your LINQ query, you'll use what I like to call the "Skip + Take" method:
public ActionResult Index(String query, int pageNumber, int pageSize)
{
...
ArticleQuery = ArticleQuery.OrderByDescending(m => m.posted).Skip(pageNumber * pageSize).Take(pageSize);
...
}
Upvotes: 0