0

我已经阅读了很多关于 MVC 中分页的文章和答案。我已经设法通过分页(使用 PagedList)创建搜索结果,但现在我需要另一件事。我有一个流派列表,我想根据一个流派浏览该流派的所有专辑。url 是 Home/Browse/1(类型的 id)。我如何分页这个结果,因为它已经有一个参数 (genreid) ?谢谢

4

2 回答 2

1

If you really want to understand how to paginate, I would suggest that you write your own custom paging logic instead of relying on someone else's PagedList abstraction.

When you need to paginate results, you need to also include 2 other aspects of the overall query that will be sent to the database: Filtering, and Sorting.

The reason why is because unless you also apply both sorting and filtering in combination with paging, you will not be able to compute the correct results.

For example, say I have a table of 100 rows and I want to show 10 rows per page. The first 10 rows sorted A-Z will be different than the first 10 rows sorted Z-A. So the table must be sorted before it can be paginated.

Your question has to do with filtering -- you want to filter out all of the albums that are not in a particular genre. Again, this means you must apply filtering before paginating the filtered results.

Ultimately your controller is going to have to hit the database to get the results. You can paginate by sending a filtered and sorted query to the database, then chopping out only a subset to display pagination to the user. However just because you can doesn't mean you should. Ideally, you would like to send the db 1 query that applies filtering, sorting, and pagination to return exactly the paged section you need.

You should be able to do this with a query like the following:

// assuming pageNumber is Nullable<int>, and is passed as action method argument
pageNumber = pageNumber ?? 1
var pageSize = 10;
var pageIndex = pageNumber.HasValue ? pageNumber.Value - 1 : 0;
var results = context.Albums
    .Where(a => a.GenreId == genreId) // filtering
    .OrderBy(a => a.GenreId) // sorting
    .Skip(pageSize * pageIndex) // skip this many rows (pagination start at)
    .Take(pageSize) // then give me this many rows (pagination chunk)
    .ToList() // execute the query against the database
;
return view(results);

Your view would then have a model type like the following:

@model IEnumerable<Album>

I assume that from using PagedList and MVC, you already know how to send the pageNumber parameter to the controller / action method. For your filtering URL (Home/Browse/1) you are passing the filtering parameter to the action method already.

If you ever decide you also want to allow the user to sort the results, you must also pass sorting information into the action method parameter. The code above assumes the natural ordering in the database (which will generally be by AlbumId).

Same goes with the pageSize. If you want to make any part of the query (sorting, filtering, pageSize, pageNumber) customizable to the user, you must pass these values as arguments to the action method. Otherwise, the controller will have to use compiled values as in the above example.

于 2012-04-10T20:56:33.653 回答
0

PagedList 的创建者在这里。你可以像这样做你要求的事情:

http://localhost:1234/home/browse/1?page=2

public class HomeController : Controller
{
  public object Browse(int genreId, int? page)
  {
    // the *page* variable is bound to the querystring value, not the route
    return View(Genres.All().ToPagedList(page ?? 1, 10);
  }
}
于 2012-04-19T12:17:05.817 回答