Pagination - X.PagedList

Dean Everhart 1,541 Reputation points
2022-12-06T18:19:28.4+00:00

Trying (unsuccessfully - error included below) to get paging to work using only X.PagedList as per the tutorial directions (pictured below including link).

267819-untitled1.png

Taken from : https://learn.microsoft.com/en-us/aspnet/mvc/overview/getting-started/getting-started-with-ef-using-mvc/sorting-filtering-and-paging-with-the-entity-framework-in-an-asp-net-mvc-application


PMC

PM> install-package x.pagedlist.mvc
Restoring packages for C:\Users\User1\Desktop\SolutionName_04 SolutionName - sort - Copy\SolutionName\ProjectName\ProjectName.csproj...
Installing NuGet package x.pagedlist.mvc 8.0.7.
Writing assets file to disk. Path: C:\Users\User1\Desktop\SolutionName_04 SolutionName - sort - Copy\SolutionName\ProjectName\obj\project.assets.json
Restored C:\Users\User1\Desktop\SolutionName_04 SolutionName - sort - Copy\SolutionName\ProjectName\ProjectName.csproj (in 164 ms).
Successfully installed 'Microsoft.AspNet.Mvc 5.2.7' to ProjectName
Successfully installed 'Microsoft.AspNet.Razor 3.2.7' to ProjectName
Successfully installed 'Microsoft.AspNet.WebPages 3.2.7' to ProjectName
Successfully installed 'Microsoft.Web.Infrastructure 1.0.0' to ProjectName
Successfully installed 'X.PagedList 8.0.7' to ProjectName
Successfully installed 'X.PagedList.Mvc 8.0.7' to ProjectName
Successfully installed 'X.PagedList.Web.Common 8.0.7' to ProjectName
Executing nuget actions took 192 ms
Time Elapsed: 00:00:00.8490185


Error(s):

Severity Code Description Project File Line Suppression State
Error (active) CS1061 'IEnumerable<Class01Name>' does not contain a definition for 'HasPreviousPage' and no accessible extension method 'HasPreviousPage' accepting a first argument of type 'IEnumerable<Class01Name>' could be found (are you missing a using directive or an assembly reference?) C:\Users\User1\Desktop\SolutionName_04 SolutionName - sort - Copy\SolutionName\ProjectName\Views\Class01Name\Index.cshtml 83


Controller Index Method

// GET: Class01Name

public async Task<IActionResult> Index(string sortOrder, string currentFilter, string searchString, int? pageNumber)  

// ********************* Previous **************************  

//public async Task<IActionResult> Index(string sortOrder, string searchString)  

{  
    ViewData["Text"] = String.IsNullOrEmpty(sortOrder) ? "text_desc" : "";  
    ViewData["Number"] = sortOrder == "Number" ? "number_desc" : "Number";  
    ViewData["CurrentFilter"] = searchString;  
    ViewData["CurrentSort"] = sortOrder;  

    if (searchString != null)  
    {  
        pageNumber = 1;  
    }  
    else  
    {  
        searchString = currentFilter;  
    }  

    var class01 = from s in _context.Class01Name  
                  select s;  

    if (!String.IsNullOrEmpty(searchString))  
    {  
        class01 = class01.Where(s => s.StringProperty01Name!.Contains(searchString)  

        || s.IntProperty01Name!.GetValueOrDefault().ToString().Contains(searchString));  

    }  

    switch (sortOrder)  
    {  
        default:  
            class01 = class01.OrderBy(s => s.StringProperty01Name);  
            break;  
        case "string_desc":  
            class01 = class01.OrderByDescending(s => s.StringProperty01Name);  
            break;  
        case "int":  
            class01 = class01.OrderBy(s => s.IntProperty01Name);  
            break;  
        case "int_desc":  
            class01 = class01.OrderByDescending(s => s.IntProperty01Name);  
            break;  
    }  

    int pageSize = 3;  
    return View(await PaginatedList<Class01Name>.CreateAsync(class01.AsNoTracking(), pageNumber ?? 1, pageSize));  
}  

View

@model IEnumerable<ProjectName.Models.Class01Name>  
  
@{  
    ViewData["Title"] = "Index";  
}  
  
<h1>Index</h1>  
  
<p>  
    <a asp-action="Create">Create New</a>  
</p>  
  
<form asp-action="Index" method="get">  
    <div class="form-actions no-color">  
        <p>  
            Find by name: <input type="text" name="SearchString" value="@ViewData["CurrentFilter"]" />  
            <input type="submit" value="Search" class="btn btn-default" /> |  
            <a asp-action="Index">Back to Full List</a>  
        </p>  
    </div>  
</form>  
  
<table class="table">  
    <thead>  
        <tr>  
            <th>  
                <a asp-action="Index" asp-route-sortOrder="@ViewData["StringProperty01"]" asp-route-currentFilter="@ViewData["CurrentFilter"]">StringProperty01Name</a>  
  
               @* <a asp-action="Index" asp-route-sortOrder="@ViewData["StringProperty01"]">@Html.DisplayNameFor(model => model.StringProperty01Name)</a>*@  
  
                @* @Html.DisplayNameFor(model => model.StringProperty01Name)*@  
            </th>  
            <th>  
                <a asp-action="Index" asp-route-sortOrder="@ViewData["IntProperty01"]" asp-route-currentFilter="@ViewData["CurrentFilter"]">IntProperty01Name</a>  
  
                @*<a asp-action="Index" asp-route-sortOrder="@ViewData["IntProperty01"]">@Html.DisplayNameFor(model => model.IntProperty01Name)</a>*@  
  
                @*@Html.DisplayNameFor(model => model.IntProperty01Name)*@  
            </th>  
            <th>  
                @Html.DisplayNameFor(model => model.DecimalProperty01Name)  
            </th>  
            <th>  
                @Html.DisplayNameFor(model => model.DateTimeProperty01Name)  
            </th>  
  
            <th>  
                @Html.DisplayNameFor(model => model.BoolProperty01Name)  
            </th>  
            <th></th>  
        </tr>  
    </thead>  
    <tbody>  
@foreach (var item in Model) {  
        <tr>  
            <td>  
                @Html.DisplayFor(modelItem => item.StringProperty01Name)  
            </td>  
            <td>  
                @Html.DisplayFor(modelItem => item.IntProperty01Name)  
            </td>  
            <td>  
                @Html.DisplayFor(modelItem => item.DecimalProperty01Name)  
            </td>  
            <td>  
                @Html.DisplayFor(modelItem => item.DateTimeProperty01Name)  
            </td>  
  
            <td>  
                @Html.DisplayFor(modelItem => item.BoolProperty01Name)  
            </td>  
            <td>  
                <a asp-action="Edit" asp-route-id="@item.Id">Edit</a> |  
                <a asp-action="Details" asp-route-id="@item.Id">Details</a> |  
                <a asp-action="Delete" asp-route-id="@item.Id">Delete</a>  
            </td>  
        </tr>  
}  
    </tbody>  
</table>  
  
@{  
    var prevDisabled = !Model.HasPreviousPage ? "disabled" : "";  
    var nextDisabled = !Model.HasNextPage ? "disabled" : "";  
}  
  
<a asp-action="Index"  
   asp-route-sortOrder="@ViewData["CurrentSort"]"  
   asp-route-pageNumber="@(Model.PageIndex - 1)"  
   asp-route-currentFilter="@ViewData["CurrentFilter"]"  
   class="btn btn-default @prevDisabled">  
    Previous  
</a>  
<a asp-action="Index"  
   asp-route-sortOrder="@ViewData["CurrentSort"]"  
   asp-route-pageNumber="@(Model.PageIndex + 1)"  
   asp-route-currentFilter="@ViewData["CurrentFilter"]"  
   class="btn btn-default @nextDisabled">  
    Next  

Model

using System.ComponentModel.DataAnnotations;         // Date Format  
using System.ComponentModel.DataAnnotations.Schema;  // Column  
  
  
  
namespace ProjectName.Models  
{  
    public class Class01Name  
    {  
        public int Id { get; set; }  
  
        public string? StringProperty01Name { get; set; }  
  
        [DataType(DataType.Date)]  
        public DateTime? DateTimeProperty01Name { get; set; }  
  
        public int? IntProperty01Name { get; set; }  
  
        public decimal? DecimalProperty01Name { get; set; }    
  
        public bool? BoolProperty01Name { get; set; }  
    }  
}  

PaginatedList.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;

namespace Project
{
public class PaginatedList<T> : List<T>
{
public int PageIndex { get; private set; }
public int TotalPages { get; private set; }

    public PaginatedList(List<T> items, int count, int pageIndex, int pageSize)  
    {  
        PageIndex = pageIndex;  
        TotalPages = (int)Math.Ceiling(count / (double)pageSize);  

        AddRange(items);  
    }  

    public bool HasPreviousPage => PageIndex > 1;  

    public bool HasNextPage => PageIndex < TotalPages;  

    public static async Task<PaginatedList<T>> CreateAsync(IQueryable<T> source, int pageIndex, int pageSize)  
    {  
        var count = await source.CountAsync();  
        var items = await source.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToListAsync();  
        return new PaginatedList<T>(items, count, pageIndex, pageSize);  
    }  
}  

}

Developer technologies | ASP.NET | ASP.NET Core
{count} votes

2 answers

Sort by: Most helpful
  1. SurferOnWww 4,711 Reputation points
    2022-12-07T00:52:33.64+00:00

    I suggest that you use the pager introduced in the following tutorial for ASP.NET Core MVC:

    Tutorial: Add sorting, filtering, and paging - ASP.NET MVC with EF Core
    https://learn.microsoft.com/en-us/aspnet/core/data/ef-mvc/sort-filter-page?view=aspnetcore-6.0

    You do not have to install any NuGet Package. The pager (PaginatedList.cs) will work on ASP.NET MVC5 application without any modification.

    0 comments No comments

  2. Anonymous
    2022-12-07T02:59:33.347+00:00

    Hi @Dean Everhart ,

    Error (active) CS1061 'IEnumerable<Class01Name>' does not contain a definition for 'HasPreviousPage' and no accessible extension method 'HasPreviousPage' accepting a first argument of type 'IEnumerable<Class01Name>' could be found (are you missing a using directive or an assembly reference?) C:\Users\User1\Desktop\SolutionName_04 SolutionName - sort - Copy\SolutionName\ProjectName\Views\Class01Name\Index.cshtml 83

    This error relates the Model Binding in the Index.cshtml page. Code as below:

    268021-image.png

    From your code, the HasPreviousPage property is in the PaginatedList class, and in the controller, it will return a PaginatedList instance to the Index.cshtml page. But in the Index.cshtml page, we can see you will use @model IEnumerable<ProjectName.Models.Class01Name> to receive the return data, so, when using the HasPreviousPage property, it will show the above error.

    To solve this issue, in the Index.cshtml page, you can change the code as below:

    @model PaginatedList<ProjectName.Models.Class01Name>  
    

    Refer to the following screenshot:

    267929-image1.gif


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".
    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    Best regards,
    Dillion

    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.