Paging - Next Page not Displaying (404 Not Found)

Dean Everhart 1,541 Reputation points
2023-02-10T14:24:27.8266667+00:00

This was working...and then it wasn't. I've combed over the code for the Action Method, View, and PaginatedList.

Based on Tutorial: https://learn.microsoft.com/en-us/aspnet/core/data/ef-mvc/sort-filter-page?view=aspnetcore-6.0#add-paging-to-students-index


FilterSort view shows all seven records

User's image


PageFilterSort shows first page but when "Next" is clicked-on...

User's image

...It does not show the next three records.

User's image


Controller

        // GET: IndexDPageFilterSort
        public async Task<IActionResult> IndexDPageFilterSort(string sortOrder, string currentFilter, string searchString, int? pageNumber)
        {
            ViewData["CurrentSort"] = sortOrder;

            ViewData["intSort"] = String.IsNullOrEmpty(sortOrder) ? "intDesc" : "";  // These are ternary statements (re: ternary conditional operators).
            ViewData["stringSort"] = sortOrder == "string" ? "stringDesc" : "string";

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

            ViewData["CurrentFilter"] = searchString;

            var variableName = from s in _context.PropertySet01
                               select s;

            if (!String.IsNullOrEmpty(searchString))
            {
                variableName = variableName.Where(s => s.String01!.Contains(searchString)
                                               || s.Int01!.GetValueOrDefault().ToString().Contains(searchString)      // int property type - requires conversion to string for search
                                               );
            }

            switch (sortOrder)
            {
                default:                                                                     // "fall-through case" in the switch statement
                    variableName = variableName.OrderBy(s => s.Int01);
                    break;

                case "intDesc":
                    variableName = variableName.OrderByDescending(s => s.Int01);
                    break;

                // _________________________________

                case "string":
                    variableName = variableName.OrderBy(s => s.String01);
                    break;
                case "stringDesc":
                    variableName = variableName.OrderByDescending(s => s.String01);
                    break;

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

View

@model PaginatedList<WebApplication01.Models.PropertySet01>

@*************** Pre-Pagination ******************@

@*@model IEnumerable<Project01Name.Models.Class01Name>*@

@************* Pre-Pagination (end) **************@

@{
    ViewData["IndexDPageFilterSort"] = "IndexDPageFilterSort";
}

<h1>IndexDPageFilterSort</h1>

<p>
    <a asp-action="Create">Create New</a>
</p>

<form asp-action="IndexDPageFilterSort" 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="IndexDPageFilterSort">Back to Full List</a>
        </p>
    </div>
</form>

<table class="table">
    <thead>
        <tr>
            <th>
                <a asp-action="IndexDPageFilterSort" asp-route-sortOrder="@ViewData["stringSort"]" asp-route-currentFilter="@ViewData["CurrentFilter"]">String01</a>
            </th>
            <th>
                <a asp-action="IndexDPageFilterSort" asp-route-sortOrder="@ViewData["intSort"]" asp-route-currentFilter="@ViewData["CurrentFilter"]">Int01</a>
            </th>
            <th>
                Bool01
            </th>
            <th>
                DateTime01
            </th>
            <th></th>
        </tr>
    </thead>
    <tbody>
        @foreach (var item in Model)
        {
            <tr>
                <td>
                    @Html.DisplayFor(modelItem => item.String01)
                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.Int01)
                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.Bool01)
                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.DateTime01)
                </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="DPageFilterSortIndex"
   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="DPageFilterSortIndex"
   asp-route-sortOrder="@ViewData["CurrentSort"]"
   asp-route-pageNumber="@(Model.PageIndex + 1)"
   asp-route-currentFilter="@ViewData["CurrentFilter"]"
   class="btn btn-default @nextDisabled">
    Next
</a>


PaginatedList

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

namespace WebApplication01
{
    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);

            this.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
Developer technologies ASP.NET Other
{count} votes

Accepted answer
  1. AgaveJoe 30,126 Reputation points
    2023-02-10T21:11:13.35+00:00

    A 404 simply means the route was not found. Anyway the 404 clearly shows the route is...

    /PropertySet01/DPageFilterSortIndex
    

    ... which correlates to the next link's action paramter.

    I think the action should be IndexDPageFilterSort?

    <a asp-action="IndexDPageFilterSort"
       asp-route-sortOrder="@ViewData["CurrentSort"]"
       asp-route-pageNumber="@(Model.PageIndex + 1)"
       asp-route-currentFilter="@ViewData["CurrentFilter"]"
       class="btn btn-default @nextDisabled">
        Next
    </a>
    
    1 person found this answer helpful.
    0 comments No comments

0 additional answers

Sort by: Most helpful

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.