- Ultimate Guide to MVC Paging!
- DataLayer Level Paging
- Business Objects for Paging
- Heart of MVC Paging
- MVC Paging Index View
- MVC Paging and PageCount Partial Views
- MVC Index Partial View for Paging
This post was revised and updated on 10/24/2020.
When paging, you usually want to have a way to allow your users to search and filter the data. When they click on search, or hit enter, or click on a column heding, you want to retain that search criteria after the page displays the results. The easiest way to do that is to keep the results in a partial view that is refreshed separately from the primary view. This way, you don’t have to fight the battle of keeping track of it.
One issue I’ve run into is that the user may search for a keyword, then they modify the keyword, think better of it, and just click a sort column. Your page posts back and the search is now for the modified keyword, which wasn’t their intention. Using the partial view method described here WILL NOT have this unwanted functionality.
When writing a partial view for the search results, I’ve added in the ability to utilize my business objects for paging, shown on post: Business Object for Paging, so that paging is implemented generically. I then use the AJAX JQuery call to refresh of the page on an column click for sorting.
Like the main view, this partial view is specifically written for the LuCategory model, there is no need to reference the model as an interface. You can specify the exact model implementation you’re expecting on the page.
Don’t make the mistake of adding the Script reference to
“jquery.unobtrusive-ajax” to this partial view as well, as that will cause some wonky results.
@using YTG.MVC.Lookups.Models
@using YTG.Models
@model SearchModel<LuCategory>
<script type="text/javascript">
function GetCategories(sortColumn) {
// Set the global values for sorting post back
var searchModel = {};
searchModel.SortColumn = sortColumn;
searchModel.PrevSortColumn = '@Model.SortColumn';
searchModel.CurrentPage = @Model.CurrentPage;
searchModel.PageSize = @Model.PageSize;
searchModel.SearchTerm = '@Model.SearchTerm';
searchModel.SortDescending = '@Model.SortDescending';
searchModel.ActiveOnly = '@Model.ActiveOnly';
$.ajax({
type: "POST",
url: "/Lookups/CatDisplay",
contentType: "application/json; charset=utf-8",
data: JSON.stringify(searchModel),
dataType: "html",
async: true,
success: function (result, status, xhr) {
$("#gridPartial").html(result)
},
error: function (xhr, status, error) {
alert("Result: " + status + " " + error + " " + xhr.status + " " + xhr.statusText)
}
});
}
</script>
<div id="CatDisplay">
<section id="main-content" class="animated fadeInUp">
<div class="text-center">
<!-- Pager -->
@if (Model.EndPage > 1)
{
await Html.RenderPartialAsync("_PagerPartial", Model);
}
</div>
<div class="panel-default">
<table width="100%" class="table table-bordered table-hover">
<thead>
<tr>
<th>Edit</th>
<th onclick="GetCategories('Name')" title="Click to Sort">Name</th>
<th onclick="GetCategories('ShortName')" title="Click to Sort">Short Name</th>
<th onclick="GetCategories('Description')" title="Click to Sort">Description</th>
<th class="text-center" title="Quantity of Items">Item Count</th>
<th class="text-center">@Html.DisplayName("Active")</th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.SortedResults)
{
<tr>
<td class="text-center">
@Html.ActionLink(" ", "Edit", "Lookups", new { id = item.Id.ToString() }, new { @class = "fas fa-edit", @title = "Id: " + item.Id })
</td>
<td>@Html.DisplayFor(modelItem => item.Name)</td>
<td>@Html.DisplayFor(modelItem => item.ShortName)</td>
<td>@Html.DisplayFor(modelItem => item.Description)</td>
<td class="text-center">@item.Items.Count().ToString()</td>
<td class="text-center">@Html.DisplayFor(modelItem => item.IsActive)</td>
</tr>
}
</tbody>
</table>
@if (Model.RecordCount == 0)
{
<div class="col-md-12">
<p class="text-center text-warning">
There are no Categories defined
</p>
<br /><br />
</div>
}
<div class="text-center">
<!-- Pager -->
@if (Model.EndPage > 1)
{
await Html.RenderPartialAsync("_PagerPartial", Model);
await Html.RenderPartialAsync("_PageCountPartial", Model);
}
</div>
</div>
</section>
</div>
I chose to not display the paging partial views when there is only one page of data using “@if (Model.EndPage > 1)”. You may prefer for them to remain, or at the very least, display the total count of records somewhere if paging is not enabled.
As I’m sure you now probably surmised, this post series took about 20 hours of effort. Please let me know if you’ve found it useful, or if you see any areas where improvements can be made (be nice). Thanks, and happy coding.