The below works to display the first page containing 3 records of 6 of a paginated list but when you click on the "Next" button, it has the following result:
[https://localhost:7045/PropertySet01?pageNumber=2
This localhost page can’t be found
No webpage was found for the web address: https://localhost:7045/PropertySet01?pageNumber=2
HTTP ERROR 404
PaginatedList.cs
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);
}
}
}
Controller
// GET: Index02FilterSortPage
public async Task<IActionResult> Index02FilterSortPage(string sortOrder, string currentFilter, string searchString, int? pageNumber)
{
ViewData["CurrentSort"] = sortOrder;
ViewData["stringSort"] = String.IsNullOrEmpty(sortOrder) ? "stringDesc" : ""; // These are ternary statements (re: ternary conditional operators).
ViewData["intSort"] = sortOrder == "int" ? "intDesc" : "int";
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));
}
switch (sortOrder)
{
default: // "fall-through case" in the switch statement
variableName = variableName.OrderBy(s => s.String01);
break;
case "stringDesc":
variableName = variableName.OrderByDescending(s => s.String01);
break;
// _________________________________
case "int":
variableName = variableName.OrderBy(s => s.Int01);
break;
case "intDesc":
variableName = variableName.OrderByDescending(s => s.Int01);
break;
}
int pageSize = 3;
return View(await PaginatedList<PropertySet01>.CreateAsync(variableName.AsNoTracking(), pageNumber ?? 1, pageSize));
}
// GET: Index01PreFilterSortPage
public async Task<IActionResult> Index01PreFilterSortPage()
{
return View(await _context.PropertySet01.ToListAsync());
}
// GET: PropertySet01/Details/5
public async Task<IActionResult> Details(int? id) // The id parameter is defined as a nullable type (int?) in cases when the id value isn't provided.
{
if (id == null || _context.PropertySet01 == null)
{
return NotFound();
}
var propertySet01 = await _context.PropertySet01
.FirstOrDefaultAsync(m => m.Id == id); // A lambda expression is passed in to the FirstOrDefaultAsync method to select movie entities that match the route data or query string value.
if (propertySet01 == null)
{
return NotFound();
}
return View(propertySet01); // If a movie is found, an instance of the Movie model is passed to the Details view:
}
// GET: PropertySet01/Create
public IActionResult Create()
{
return View();
}
View
@model PaginatedList<WebApplication01.Models.PropertySet01>
@*************** Pre-Pagination ******************@
@*@model IEnumerable<Project01Name.Models.Class01Name>*@
@************* Pre-Pagination (end) **************@
@{
ViewData["Title"] = "Index02FilterSortPage";
}
<h1>Index02FilterSortPage</h1>
<p>
<a asp-action="Create">Create New</a>
</p>
<form asp-action="Index02FilterSortPage" 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="Index02FilterSortPage" asp-route-sortOrder="@ViewData["stringSort"]" asp-route-currentFilter="@ViewData["CurrentFilter"]">String01</a>
</th>
<th>
<a asp-action="Index02FilterSortPage" 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="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
</a>