Support us .Net Basics C# SQL ASP.NET Aarvi MVC Slides C# Programs Subscribe Download

Part 64 - Implement sorting in asp.net mvc

Suggested Videos 
Part 61 - Named sections in layout files in mvc
Part 62 - Implementing search functionality in asp.net mvc
Part 63 - Implement paging in asp.net mvc

In this video, we will discuss, implementing sort functionality in an asp.net mvc application. We will be working with the example that we started in Part 62. So, please watch Parts 62 and 63 before proceeding with this video.



We want to support bi-directional sorting by Name and Gender columns. Here's the requirement
1. Name & Gender columns must be click-able hyperlinks
2. Clicking on the column headers should sort the data. If the data is not already sorted by the column on which you have clicked, the data should be sorted in ascending order. Clicking again on the same column should sort the data in descending order.
3. By default, the data should be sorted by "Name" in ascending order.



By the end of this video, the output should be as shown below. Notice that "Name" and "Gender" columns are rendered as hyperlinks, which the user can click to sort data.
sorting in mvc

Step 1: Modify the "Index()" action method in HomeController as shown below.
public ActionResult Index(string searchBy, string search, int? page, string sortBy)
{
    ViewBag.NameSort = String.IsNullOrEmpty(sortBy) ? "Name desc" : "";
    ViewBag.GenderSort = sortBy == "Gender" ? "Gender desc" : "Gender";

    var employees = db.Employees.AsQueryable();
            
    if (searchBy == "Gender")
    {
        employees = employees.Where(x => x.Gender == search || search == null);
    }
    else
    {
        employees = employees.Where(x => x.Name.StartsWith(search) || search == null);
    }

    switch (sortBy)
    {
        case "Name desc":
            employees = employees.OrderByDescending(x => x.Name);
                break;
        case "Gender desc":
                employees = employees.OrderByDescending(x => x.Gender);
                break;
        case "Gender":
                employees = employees.OrderBy(x => x.Gender);
                break;
        default:
            employees = employees.OrderBy(x => x.Name);
                break;
    }

    return View(employees.ToPagedList(page ?? 1, 3));
}

Step 2: Modify the code in Index.cshtml view as shown below. Please pay attention to the code highlighted with Grey colour.
@using PagedList;
@using PagedList.Mvc;

@model PagedList.IPagedList<MVCDemo.Models.Employee>

@{
    ViewBag.Title = "Index";
}
<link href="~/Content/PagedList.css" rel="stylesheet" type="text/css" />
<div style="font-family:Arial">
<h2>Employee List</h2>
<p>
    @using (@Html.BeginForm("Index", "Home", FormMethod.Get))
    {
        <b>Search By:</b>
        @Html.RadioButton("searchBy", "Name", true) <text>Name</text>
        @Html.RadioButton("searchBy", "Gender") <text>Gender</text><br />
        @Html.TextBox("search") <input type="submit" value="search" />
        
    }
</p>
<table border="1">
    <tr>
        <th>
            @Html.ActionLink("Name", "Index", new { sortBy = ViewBag.NameSort, searchBy = Request["searchBy"], search = Request["search"] })
        </th>
        <th>
            @Html.ActionLink("Gender", "Index", new { sortBy = ViewBag.GenderSort, searchBy = Request["searchBy"], search = Request["search"] })
        </th>
        <th>
            @Html.DisplayNameFor(model => model.First().Email)
        </th>
        <th>Action</th>
    </tr>
@if (Model.Count() == 0)
{
    <tr>
        <td colspan="4">
            No records match search criteria
        </td>
    </tr>
}
else
{
    foreach (var item in Model)
    {
        <tr>
            <td>
                @Html.DisplayFor(modelItem => item.Name)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Gender)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Email)
            </td>
            <td>
                @Html.ActionLink("Edit""Edit", new { id = item.ID }) |
                @Html.ActionLink("Details", "Details"new { id = item.ID }) |
                @Html.ActionLink("Delete""Delete"new { id = item.ID })
            </td>
        </tr>
    }
}
</table>
@Html.PagedListPager(Model, page => Url.Action("Index", new { page, searchBy = Request.QueryString["searchBy"], search = Request.QueryString["search"], sortBy = Request["sortBy"] }), new PagedListRenderOptions() { Display = PagedListDisplayMode.IfNeeded })
</div>

4 comments:

  1. Thanks Sir unbeatable videos .
    one of my query is that when we have int and decimal type columns and with those columns i want startwith type of functionality means that if i type "-" then it will filter decimal column with negative sign and again if we type -1 then it will filter those rows who having startup no in column. Sir i faced this type of problem so i convert all columns in string and filter rows but i think it is not a proper solution.

    ReplyDelete
  2. Hi,
    I am getting the following error:

    "The method 'Skip' is only supported for sorted input in LINQ to Entities. The method 'OrderBy' must be called before the method 'Skip'"

    in the following statement:

    return View( employee.ToPagedList(page ?? 1, 3));

    Please let me know what is wrongs with the code.
    I am using VS2012.

    Thanks

    ReplyDelete
  3. My sorting is working fine but the search functionality is lost now. What should I do?

    ReplyDelete
  4. Hi,
    If you Search By: Gender and leave field text empty we receive an empty table with "No rows match search criteria" .
    But if we Search by: Name and leave field text empty we receive the table with all the employees.

    How to fix this?

    ReplyDelete

It would be great if you can help share these free resources