During this session, we talk about Sort in ASP.NET Core and implementing this feature on the Web App that we have developed until this session for this tutorial. Generally, we can sort a list in Ascending or Descending format. Thus, in this session, we implement both formats to cover more detail about this topic. Also in this session, we use switch case structure to avoid using several If else structures.
Sort List in ASP.NET Core
To implement this feature on a Web App, we need to modify the View to enable the users to submit their requests for sorting. There are several ways to deploy these changes and in this tutorial, we use Query String. Therefore, we start this process by changing the respective View.
If you remember during the previous sessions, we develop a list to view the list of Costs (Cost/Index). Now we change the view and change the Cost and the Payment Method property to the anchor element. Then with asp-route Tag Helper passes the required Query String to the Controller.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
<th>ID</th> @{ var sortBy = Context.Request.Query["sortby"] == "amount" ? "amountdesc" : "amount"; } <th><a asp-action="index" asp-route-sortby="@sortBy" asp-route-page="@Context.Request.Query["page"]" asp-route-searchby="@Context.Request.Query["searchby"]" asp-route-searchfor="@Context.Request.Query["searchfor"]">Amount</a></th> <th>Category</th> <th>Comment</th> @{ sortBy = Context.Request.Query["sortby"] == "paymentmethod" ? "paymentmethoddesc" : "paymentmethod"; } <th><a asp-action="index" asp-route-sortby="@sortBy" asp-route-page="@Context.Request.Query["page"]" asp-route-searchby="@Context.Request.Query["searchby"]" asp-route-searchfor="@Context.Request.Query["searchfor"]">Payment Method</a></th> <th colspan="3" class="text-center">Actions</th> </tr> |
As you can see above we use asp-route Tag Helper to pass the required data to the Controller. Also, the full code of the Cost/Index view is available below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
@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> @{ var sortBy = Context.Request.Query["sortby"] == "amount" ? "amountdesc" : "amount"; } <th><a asp-action="index" asp-route-sortby="@sortBy" asp-route-page="@Context.Request.Query["page"]" asp-route-searchby="@Context.Request.Query["searchby"]" asp-route-searchfor="@Context.Request.Query["searchfor"]">Amount</a></th> <th>Category</th> <th>Comment</th> @{ sortBy = Context.Request.Query["sortby"] == "paymentmethod" ? "paymentmethoddesc" : "paymentmethod"; } <th><a asp-action="index" asp-route-sortby="@sortBy" asp-route-page="@Context.Request.Query["page"]" asp-route-searchby="@Context.Request.Query["searchby"]" asp-route-searchfor="@Context.Request.Query["searchfor"]">Payment Method</a></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"], sortby = @Context.Request.Query["sortby"]}), new X.PagedList.Web.Common.PagedListRenderOptions { LiElementClasses = new string[] {"page-item"}, PageClasses = new string[] { "page-link" } }) |
Next, we need to change ICostRepositoy and then the respective repository to perform the sort feature on the list, based on the client request.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
public interface ICostRepository { Cost GetCostByID(int id); IEnumerable<Cost> GetAllCost(); Cost Create(Cost NewCost); Cost Update(Cost UpdateCost); Cost Delete(int id); List<CostList> GetCostList(string searchby, string searchfor, string sortby); } } |
As you can see, now the GetCostList method expects a new input element which is sortby and we can sort the list based on the sort by value.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
public List<CostList> GetCostList(string searchby, string searchfor, string sortby) { 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 }); } switch (sortby) { case "amount": costList = costList.OrderBy(o => o.Amount).ToList(); break; case "amountdesc": costList = costList.OrderByDescending(o => o.Amount).ToList(); break; case "paymentmethod": costList = costList.OrderBy(o => o.PaymentMethod).ToList(); break; case "paymentmethoddesc": costList = costList.OrderByDescending(o => o.PaymentMethod).ToList(); break; default: break; } return costList; } |
As it has been shown above, the sort has been implemented on the list at the end of this method with OrderBy and OPrderByDescending methods. Also, we use a switch case structure to evaluate the sortby value.
Finally, we can change the Controller to receive the data from the View.
1 2 3 4 5 6 7 8 9 10 |
[HttpGet] public IActionResult Index(string searchby, string searchfor, int? page, string sortby) { var costs = costRepository.GetCostList(searchby, searchfor,sortby).ToPagedList(page ?? 1, 5); return View(costs); } |
As it might be seen above, we receive the sortby value as an input parameter, then we send it to the repository and receive the sorted list to be passed to the View.
If you need more details, watch this session video. Also, to be updated about our coming sessions, follow us on Instagram, Facebook, Telegram, or YouTube. Moreover, you can have access to the list of all sessions HERE and you can download this session source code from our GitHub.
You can download this Session Slides form HERE.