Question

I want to create a pagination in MVC 4 with entity data model. My Home/NameDetailsPage works fine which return me all the rows at a time. But I want to show this data with pagination as there are so many rows. So i have tried like this

 public ActionResult NameDetailsPage(int page)
    {

        var context = new BlogContext();
        IQueryable<string> list;
        list = from m in context.Blogs.OrderBy(m => m.BlogId)
               select m.Name;

         ViewBag.total=list.ToArray().Length;

        return View("NameDetails", list.Skip(page * 4).Take(4));
    }

here page number indicates that I want to skip page*4 rows to get the next 4 rows. Unfortunately I have found these error.

The parameters dictionary contains a null entry for parameter 'page' of non-nullable type 'System.Int32' for method 'System.Web.Mvc.ActionResult NameDetailsPage(Int32)' in 'webpro.Controllers.HomeController'.
An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter.
Parameter name: parameters

What should I do ? Thanks in advance.

Was it helpful?

Solution

The error gives you the answer; page is a non-optional parameter. In other words the routing engine cannot find a suitable parameter-less action method, or an action method with optional parameters.

You need to set page as an optional parameter

public ActionResult NameDetailsPage(int page = 1)
{
...

Or pass the default value via a route definition.

OTHER TIPS

Based on the error, making the parameter Nullable satisfies the condition expected. This is demonstrated at the head of the method NameDetailsPage() below.

Another suggestion about LINQ to Entities, not asked, but provided as well, is to avoid pulling the whole set locally, see the use of .Count() below.

Code organization wise, the reason I put the paging bits at the top is that if there is something amiss, ie that the client requested page -1 (add validation), this is dealt with ahead of hitting the data store.

I also changed the LINQ query itself to use the extension methods exclusively. This could have been done instead by changing the LINQ query to use integrated query syntax exclusively. The point is to use one or the other as much as possible. It is an unnecessary difficulty placed on the maintainer of the code to have to think about both syntaxes.

public ActionResult NameDetailsPage(int? page)
{
    // TODO: add validation of parameters
    // TODO: REVIEW page size as a hard-coded constant will likely become a user-input
    const int pageSize = 4;
    var pageNumberRequested = page ?? 1; //<< assuming page is 1-based, a person would say "page 1"
    var skipRecords = (pageNumberRequested - 1) * pageSize;
    var takeRecords = pageSize;

    var context = new BlogContext();
    var blogEntries = context.Blogs.OrderBy(blog => blog.BlogId)
                          .Select(blog => blog.Name);

    var totalCount = blogEntries.Count(); //<< let the server-side use an index rather than shipping all of the records, which is a huge amount of Net I/O, then using a huge amount of RAM to create an array, only to get the number of elements in the array.

    var pageOfBlogEntries = blogEntries.Skip(skipRecords).Take(takeRecords);

    ViewBag.total = totalCount;

    return View("NameDetails", pageOfBlogEntries);
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top