در این جلسه، قصد داریم تا به پیادهسازی صفحهبندی یا Paging در ASP.NET Core MVC بپردازیم. در صورتی که تعداد رکوردهای ارسال شده به یک لیست برای نمایش بیش از یک حد مورد نظر باشد، مشکلاتی برای بارگذاری صفحه مذکور بوجود میآید. به عنوان مثال، زمان بارگذاری با توجه به حجم داده ارسالی طولانیتر شده و صفحه کندتر بارگذاری میگردد. همچنین نمای صفحه با توجه به تعداد رکوردها ممکن است ظاهر مناسبی نداشته باشد. ضمنا، کاربر ذهنیتی در مورد تعداد کلی رکوردها نخواهد داشت و رسیدن به بالا و پایین (هدر و فوتر) سایت برای کاربر ممکن است دشوار گردد. برای رفع مشکلات فوق، بهتر است در زمان نمایش لیستها از صفحهبندی (Pagination) استفاده گردد.
مزایای استفاده از صفحهبندی (Pagination)؟
- افزایش سرعت بارگذاری صفحه
- پیمایش راحتتر صفحه وب
- ظاهر مناسبتر
- اسکرول کمتر در صفحه
- ارائه حدودی تعداد رکوردها به کاربر
پیادهسازی Paging در ASP.NET Core MVC
جهت پیادهسازی صفحهبندی و یا Paging در ASP.NET Core MVC روشهای مختلفی وجود دارد. ما در این دوره آموزشی، Pagination را با استفاده از NuGet پکیج X.PagedList.Mvc.Core پیادهسازی میکنیم. پس ابتدا با راست کلیک برروی Dependences پنل مدیریت پکیج NuGet را اجرا میکنیم. سپس اقدام به نصب پکیج ذکر شده میکنیم.
حال میتوانیم از متدهای مربوط به پکیج X.PagedList استفاده نماییم. برای ارسال لیست از کنترلر به نما به صورت صفحهبندی، میتوانیم از متد ToPagedList بروی لیست مورد نظر استفاده کنیم. درون این متد میتوانیم شماره صفحه جاری و تعدادرکورد در صفحه را تنظیم نماییم. ما این کار را بروی پروژه مربوط به این دوره آموزشی و لیست مربوط به Cost انجام میدهیم.
[HttpGet]
public IActionResult Index(string searchby, string searchfor, int? page)
{
//var costs = costRepository.GetAllCost();
var costs = costRepository.GetCostList(searchby, searchfor).ToPagedList(page ?? 1, 5);
return View(costs);
}
همانگونه که مشاهده میکنیم، شماره صفحه جاری به عنوان پارامتر ورودی این اکشن متد میباشد که توسط Query String ارسال میشود. ضمنا درون متد ToPagedList صفحه جاری و مقدار پیش فرض تعیین گردیده است. همچنین تعداد رکورد در صفحه بروی 5 تنظیم شده است.
سپس درون نما میبایست ابتدا پکیج مورد نظر اضافه گردد. سپدر این صورت میتوانیم Pagination را با استفاده از Html هلپر PagedListPager که مربوط به این پکیج میباشد به نما اضافه نماییم. این Html Helper برای ایجاد لینک صفحات، نیاز به لیست داده و شمارنده صفحه به صورت یک تابع دارد. همچنین جهت ویرایش نمای مربوط به Pagination میتوانیم از PagedListRenderOptions درون این هلپر استفاده نماییم.
ما در این پروژه عملیات Paging را بروی اکشن متد Index از کنترلر CostController پیادهسازی کردیم.
تغییرات مورد نیاز بروی نمای Index
@model IEnumerable<CostList>
@using X.PagedList;
@using X.PagedList.Mvc.Core;
.
.
.
@Html.PagedListPager((IPagedList) Model, page => Url.Action("Index", new {page = page,
searchfor = @Context.Request.Query["searchfor"], searchby = @Context.Request.Query["searchby"]}),
new X.PagedList.Web.Common.PagedListRenderOptions {
LiElementClasses = new string[] {"page-item"},
PageClasses = new string[] { "page-link" }
})
نمای کلی از View
@model IEnumerable<CostList>
@using X.PagedList;
@using X.PagedList.Mvc.Core;
@{
ViewBag.Title = "Cost List";
}
<div class="row">
<div class=col-3>
<a asp-controller="cost" asp-action="create" class="btn btn-primary mx-2 my-2">Create New Cost</a>
</div>
<div class="col-6 offset-3">
<form asp-controller="Cost" asp-action="Index" method="get" class="my-2 mx-2">
<div class="input-group">
<select class="form-select" id="inputSearch" name="searchby">
<option selected value="">Search by...</option>
<option value="comment">Comment</option>
<option value="category">Category</option>
</select>
<input name="searchfor" class="form-control" id="inputSearch" aria-describedby="inputSearchComment" aria-label="Search">
<button class="btn btn-outline-secondary" type="submit" id="inputSearch">Search</button>
<a class="btn btn-outline-primary" type="button" asp-controller="cost" asp-action="index">Clear Search</a>
</div>
</form>
</div>
</div>
<table class="table table-dark">
<thead>
<tr>
<th>ID</th>
<th>Amount</th>
<th>Category</th>
<th>Comment</th>
<th>Payment Method</th>
<th colspan="3" class="text-center">Actions</th>
</tr>
</thead>
<tbody>
@foreach (var cost in Model)
{
<tr>
<td>@cost.ID</td>
<td>@cost.Amount</td>
<td>@cost.CategoryName</td>
<td>@cost.Comment</td>
<td>@cost.PaymentMethod</td>
<form asp-controller="cost" asp-action="delete" asp-route-id="@cost.ID" method="post">
<td><a class="btn btn-primary d-block" asp-controller="cost" asp-action="detail" asp-route-id="@cost.ID">View</a></td>
<td><a class="btn btn-info btn-block d-block" asp-controller="cost" asp-action="update" asp-route-id="@cost.ID">Edit</a></td>
<td><button class="btn btn-danger btn-block d-block" type="submit">Delete</button></td>
</form>
</tr>
}
</tbody>
</table>
@Html.PagedListPager((IPagedList) Model, page => Url.Action("Index", new {page = page,
searchfor = @Context.Request.Query["searchfor"], searchby = @Context.Request.Query["searchby"]}),
new X.PagedList.Web.Common.PagedListRenderOptions {
LiElementClasses = new string[] {"page-item"},
PageClasses = new string[] { "page-link" }
})
رفع مشکل جستجو درون فیلد با مقادیر تهی در EF Core
در صورتی که تمایل به انجام عملیات جستجو بروی فیلدی که ممکن است حاوی مقادیر تهی باشد (Nullable) دارید، بهتر است جهت جلوگیری از بروز خطا، تهی بودن مقدار را بررسی نمایید. روشهای مختلفی برای رفع این مشکل وجود دارد که ما در این آموزش از بررسی تهی بودن مقدار فیلد استفاده مینماییم.
با توجه به جستجو درون فیلد Comment (فیلد با احتمال وجود مقدار تهی) از موجودیت Cost که در جلسه گذشته پیاده سازی نمودیم، میبایست تغییرات زیر را برروی کد مربوطه اعمال نماییم.
public List<CostList> GetCostList(string searchby, string searchfor)
{
var CL = context.Costs.Join(context.Categories, costen => costen.CategoryID, caten => caten.ID, (costen, caten) => new { costen, caten }).
Select(sel => new
{
sel.costen.ID,
sel.costen.Amount,
sel.costen.Comment,
sel.costen.PaymentMethod,
sel.caten.CategoryName
}).ToList();
if(searchby == "comment" && searchfor != null)
{
CL = CL.Where(ser => ser.Comment!=null ? ser.Comment.ToLower().Contains(searchfor.ToLower()) : ser.Comment != null).ToList();
}
if (searchby == "category" && searchfor != null)
{
CL = CL.Where(ser => ser.CategoryName.ToLower() == searchfor.ToLower()).ToList();
}
List<CostList> costList = new();
foreach (var cost in CL)
{
costList.Add(new CostList
{
ID = cost.ID,
Amount = cost.Amount,
Comment = cost.Comment,
PaymentMethod = cost.PaymentMethod,
CategoryName = cost.CategoryName
});
}
return costList;
}
همانگونه که در قطعه کد فوق مشاهده میکنیم، در قسمت مربوط به جستجو فیلد Comment تهی بودن آن بررسی میگیردد و در صورت تهی نبودن شرط لازم چک میشود.
در صورت نیاز به جزئیات بیشتر، میتوانید ویدئو آموزشی این جلسه را تماشا نمایید. همچنین برای آگاهی از جلسات بعدی این دوره آموزشی، ما را در اینستاگرام، تلگرام، یوتیوب و آپارات دنبال کنید. ضمنا لیست کامل جلسات در این قسمت در دسترس شما میباشد و سورس کد این جلسه را میتوانید از GitHub ما دانلود نمایید.
دانلود اسلایدهای آموزشی این جلسه از اینجا