Paging, Sorting, And Filtering With Partial View In ASP.NET MVC 5

Description

In my last series on Restful API in ASP.NET, we have successfully created an ASP.NET Web Application with the ASP.NET Web API Project Template. Now, in this article I am describing the use of Partial view in MVC 5 with the help of my old API application. We will change up the application with the new requirement.

So, let’s have a look at Partial View. Partial View performs as user controls (.ascx). With the help of Partial view, we can create a view which will be brought to pass in a parent view. Here in this article, we will perform Paging, Sorting and Filtering with the use of Partial View in the MVC 5.

Now, I am assuming that you have gone through my previous article so that I can easily create a new section to perform the current requirement.

Prerequisites

You must have Visual Studio 2013 or later version to work on MVC 5 based web applications.

Getting Started

In this section, we will categorized our application into the following three parts:

  • Paging
  • Sorting
  • Filtering

Adding Web Project

First we have to add a Web Project in our solution. Please follow the steps below to perform:

Step 1:
In the Solution Explorer, right click on the Solution and add a new Solution Folder named "Web”.

Adding Solution Folder
                                             Figure 1: Adding Solution Folder

Step 2: Now right click on the Web folder and click on "Add New Project”.

Adding New Project
                                          Figure 2: Adding New Project

Step 3: Select the "Web" option from the left pane in the next wizard and click on "ASP.NET Web application”.

Adding Web Application
                                                Figure 3: Adding Web Application

Step 4: In the next "ASP.NET” wizard, select the MVC Project Template.

One ASP.NET Wizard
                                                Figure 4:
One ASP.NET Wizard

That’s it. You have successfully created an MVC Project.

Paging

In this section we have to change the structure of the stored procs, methods in API; so that we can create a view to get the records. So, follow the following procedure to perform this section:

Step 1: Modify the Stored Procedure as the Paging requirement from the following script:
  1. ALTER PROC [dbo].[CC_GetCricketerList]  
  2.     @PageNumber INT ,  
  3.     @PageSize INT  
  4. AS  
  5.     BEGIN  
  6.         SELECT  ROW_NUMBER() OVER ( ORDER BY ID DESC ) [RowNo] ,  
  7.                 *,  
  8.                 COUNT(ID) OVER ( ) [TotalCount]   
  9.         FROM    dbo.CricketerProfile (NOLOCK)  
  10.         ORDER BY ID  
  11.                 OFFSET ( @PageNumber - 1 ) * @PageSize ROWS  
  12.     FETCH NEXT @PageSize ROWS ONLY;  
  13.     END;  
Step 2: Modify the following methods as per the following classes:

CricketerProfile.CS
  1. public class CricketerProfile : Result  
  2. {  
  3.     public int Id { getset; }  
  4.     public string Name { getset; }  
  5.     public int ODI { getset; }  
  6.     public int Tests { getset; }  
  7.     public int OdiRuns { getset; }  
  8.     public int TestRuns { getset; }  
  9.     public int Type { getset; }  
  10.     public int TotalCount { getset; }  
  11. }  
CricketerDAL.CS
  1. public List<CricketerProfile> GetCricketerList(int PageNumber, int PageSize)  
  2. {  
  3.     List<CricketerProfile> objGetCricketers = null;  
  4.     objDB = new SqlDatabase(ConnectionString);  
  5.     using (DbCommand objcmd = objDB.GetStoredProcCommand("CC_GetCricketerList"))  
  6.     {  
  7.         try  
  8.         {  
  9.             objDB.AddInParameter(objcmd, "@PageNumber", DbType.Int32, PageNumber);  
  10.             objDB.AddInParameter(objcmd, "@PageSize", DbType.Int32, PageSize);  
  11.   
  12.             using (DataTable dataTable = objDB.ExecuteDataSet(objcmd).Tables[0])  
  13.             {  
  14.                 objGetCricketers = ConvertTo<CricketerProfile>(dataTable);  
  15.             }  
  16.         }  
  17.         catch (Exception ex)  
  18.         {  
  19.             throw ex;  
  20.             return null;  
  21.         }  
  22.     }  
  23.     return objGetCricketers;  
  24. }  
CricketerBL.CS
  1. public List<CricketerProfile> GetCricketerList(int PageNumber, int PageSize)  
  2. {  
  3.     List<CricketerProfile> ObjCricketers = null;  
  4.     try  
  5.     {  
  6.         ObjCricketers = new CricketerDAL().GetCricketerList(PageNumber, PageSize);  
  7.     }  
  8.     catch (Exception)  
  9.     {  
  10.   
  11.         throw;  
  12.     }  
  13.     return ObjCricketers;  
  14. }  
Method in API:
  1. [HttpGet, ActionName("GetCricketerList")]  
  2. public HttpResponseMessage GetCricketerList(int PageNumber, int PageSize)  
  3. {  
  4.     Result result;  
  5.     cricketerBL = new CricketerBL();  
  6.     try  
  7.     {  
  8.         var cricketerList = cricketerBL.GetCricketerList(PageNumber, PageSize);  
  9.   
  10.         if (!object.Equals(cricketerList, null))  
  11.         {  
  12.             response = Request.CreateResponse<List<CricketerProfile>>(HttpStatusCode.OK, cricketerList);  
  13.         }  
  14.     }  
  15.     catch (Exception ex)  
  16.     {  
  17.         result = new Result();  
  18.         result.Status = 0;  
  19.         result.Message = ex.Message;  
  20.         response = Request.CreateResponse(HttpStatusCode.InternalServerError, result);  
  21.     }  
  22.     return response;  
  23. }  
Step 3: Now first add a reference of Models project in the Web Project.

Adding Reference Wizard
                                             Figure 5: Adding Reference Wizard

Step 4: Add a class  named "CricketerInfo” in the Models folder of the Web Project and modify the code from the following code in that class:
  1. public class CricketerInfo  
  2. {  
  3.    public List<BestCricketers.Models.CricketerProfile> cricketerProfile { getset; }  
  4. }  
Step 5: Build the solution.

Step 6: Right click on the Controllers folder and go to Add, then click Controller

Adding Controller
                                          Figure 6: Adding Controller

Step 7: Now in the "Add Scaffold” wizard, select the "MVC 5 Controller - Empty":

 Add Scaffold Wizard
                                                Figure 7: Add Scaffold Wizard

Step 8: In the next wizard, enter the name "CricketersController

Add Controller
                                                   Figure 8: Add Controller

Step 9: Add the following keys in "Web.Config” file:
  1. <add key="DefaultPageSize" value="5"/>  
  2. <add key="ApiUrl" value="http://localhost:6416/"></add>  
Note: Please change the API Url as per your project.

Step 10: Add the following method in the "CricketersController"
  1. /// <summary>  
  2. /// This method is used to get cricketers list.  
  3. /// </summary>  
  4. /// <param name="PageNumber"></param>  
  5. /// <param name="PageSize"></param>  
  6. /// <returns></returns>  
  7. [HttpGet, ActionName("GetBestCricketers")]  
  8. public async Task<ActionResult> GetBestCricketers(int? PageNumber, int? PageSize)  
  9. {  
  10.     List<CricketerProfile> cricketersList = new List<CricketerProfile>();  
  11.     var httpClient = new HttpClient();  
  12.     httpClient.BaseAddress = new Uri(ConfigurationManager.AppSettings["ApiUrl"]);  
  13.     httpClient.DefaultRequestHeaders.Clear();  
  14.     httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));  
  15.     HttpResponseMessage response;  
  16.   
  17.     if (object.Equals(PageNumber, null))  
  18.     {  
  19.         PageNumber = 1;  
  20.     }  
  21.     if (object.Equals(PageSize, null))  
  22.     {  
  23.         PageSize = Convert.ToInt32(ConfigurationManager.AppSettings["DefaultPageSize"]);  
  24.   
  25.     }  
  26.     ViewBag.PageNumber = PageNumber;  
  27.     ViewBag.PageSize = PageSize;  
  28.   
  29.     response = httpClient.GetAsync(string.Format("api/Cricketers/GetCricketerList?PageNumber={0}&PageSize={1}", PageNumber, PageSize)).Result;  
  30.   
  31.     response.EnsureSuccessStatusCode();  
  32.     var responseAsString = await response.Content.ReadAsStringAsync();  
  33.     cricketersList = JsonConvert.DeserializeObject<List<BestCricketers.Models.CricketerProfile>>(responseAsString);  
  34.     return View("~/Views/Cricketers/BestCricketers.cshtml"new CricketerInfo() { cricketerProfile = cricketersList });  
  35. }  
Step 11: Go to Solution Explorer, right click on the web project, then click References

Adding NuGet Package
      Figure 9: Adding NuGet Package

Step 12: Search out PagedList.Mvc and install this package:

Adding PagedList in MVC 5
                                          Figure 10: Adding PagedList in MVC 5

Step 13: Now go to View, then Cricketers and add a new view in this folder:

Adding View in MVC 5
                                             Figure 11: Adding View in MVC 5

Step 14: Add the jQuery Unobtrusive ajax from the NuGet Package as shown below:

JQuery Unobtrusive Ajax
                                          Figure 12: JQuery Unobtrusive Ajax

Step 15: Add the following code in the View:
  1. @model BestCricketersWeb.Models.CricketerInfo  
  2. @using PagedList;  
  3. @{  
  4.     ViewBag.Title = "BestCricketers";  
  5. }  
  6. <script src="~/Scripts/jquery-1.10.2.js"></script>  
  7. <script src="~/Scripts/jquery.unobtrusive-ajax.js"></script>  
  8. <h2>Best Cricketers</h2>  
  9.   
  10. @using (Ajax.BeginForm("GetBestCricketersInfo""Cricketers"nullnew AjaxOptions() { LoadingElementId = "", HttpMethod = "Get", UpdateTargetId = "CricketersGrid" }))  
  11. {  
  12.     <div class="CricketersList">  
  13.         <div id="CricketersGrid">             
  14.             @Html.Partial("~/Views/Cricketers/_BestCricketersPartial.cshtml"new StaticPagedList<BestCricketers.Models.CricketerProfile>(Model.cricketerProfile, Convert.ToInt32(ViewBag.PageNumber), Convert.ToInt32(ViewBag.PageSize), Model.cricketerProfile.Count > 0 ? Model.cricketerProfile.FirstOrDefault().TotalCount : 0))  
  15.         </div>  
  16.     </div>  
  17. }  
Step 16: Add the following code in the CricketersController.
  1. /// <summary>  
  2. /// This method is used to get cricketers list.  
  3. /// </summary>  
  4. /// <param name="page"></param>  
  5. /// <param name="pageSize"></param>  
  6. /// <returns></returns>  
  7. [HttpGet, ActionName("GetBestCricketersInfo")]  
  8. public async Task<ActionResult> GetBestCricketersInfo (int? page, int? pageSize)  
  9. {  
  10.     List<CricketerProfile> cricketersList = new List<CricketerProfile>();  
  11.     var httpClient = new HttpClient();  
  12.     httpClient.BaseAddress = new Uri(ConfigurationManager.AppSettings["ApiUrl"]);  
  13.     httpClient.DefaultRequestHeaders.Clear();  
  14.     httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));  
  15.     HttpResponseMessage response;  
  16.   
  17.     if (object.Equals(page, null))  
  18.     {  
  19.         page = 1;  
  20.     }  
  21.     if (object.Equals(pageSize, null))  
  22.     {  
  23.         pageSize = Convert.ToInt32(ConfigurationManager.AppSettings["DefaultPageSize"]);  
  24.   
  25.     }  
  26.     ViewBag.PageNumber = page;  
  27.     ViewBag.PageSize = pageSize;  
  28.   
  29.     response = httpClient.GetAsync(string.Format("api/Cricketers/GetCricketerList?PageNumber={0}&PageSize={1}", page, pageSize)).Result;  
  30.   
  31.     response.EnsureSuccessStatusCode();  
  32.     var responseAsString = await response.Content.ReadAsStringAsync();  
  33.     cricketersList = JsonConvert.DeserializeObject<List<CricketerProfile>>(responseAsString);  
  34.     return PartialView("~/Views/Cricketers/_BestCricketersPartial.cshtml"new StaticPagedList<CricketerProfile>(cricketersList, Convert.ToInt32(page), Convert.ToInt32(pageSize), cricketersList.Count > 0 ? cricketersList.FirstOrDefault().TotalCount : 0));  
  35. }  
Step 17: Add the Partial View as in the following screenshot:

Adding Partial View
                                             Figure 13: Adding Partial View

Step 18: Add the following code in the partial view page:
  1. @model PagedList.IPagedList<BestCricketers.Models.CricketerProfile>  
  2. @using PagedList.Mvc  
  3.   
  4. <table class="table-responsive table">  
  5.     <thead>  
  6.         <tr>  
  7.             <th>Name</th>  
  8.             <th>ODI</th>  
  9.             <th>Tests</th>  
  10.             <th>ODI Runs</th>  
  11.             <th>Test Runs</th>  
  12.         </tr>  
  13.     </thead>  
  14.     <tbody>  
  15.         @if (Model.Count > 0)  
  16.         {  
  17.             foreach (var cricketer in Model)  
  18.             {  
  19.                 <tr>  
  20.                     <td>@cricketer.Name</td>  
  21.                     <td>@cricketer.ODI</td>  
  22.                     <td>@cricketer.Tests</td>  
  23.                     <td>@cricketer.OdiRuns</td>  
  24.                     <td>@cricketer.TestRuns</td>  
  25.                 </tr>  
  26.             }  
  27.         }  
  28.         else  
  29.         {  
  30.             <tr>  
  31.                 <td>  
  32.                     No Data Found  
  33.                 </td>  
  34.             </tr>  
  35.         }  
  36.     </tbody>  
  37. </table>  
  38. @if (Model.TotalItemCount > Convert.ToInt32(System.Configuration.ConfigurationManager.AppSettings["DefaultPageSize"]))  
  39. {  
  40.     <div class="pagingBox">  
  41.         <input id="HiddenPageSize" name="PageSize" type="hidden" />  
  42.         <input id="HiddenPage" name="Page" type="hidden" />  
  43.         <span class="selectBoxes display_none_mobile">  
  44.             @Html.DropDownList("PageSize"new SelectList(new Dictionary<stringint> { { "10", 10 }, { "20", 20 } }, "Key""Value", Convert.ToString(ViewBag.PageSize)), new { id = "pagesizelist" })  
  45.         </span>  
  46.         <div class="pagerecord display_none_mobile">  
  47.             Records  
  48.   
  49.             Page @(Model.PageCount < Model.PageNumber ? 0 : Model.PageNumber) of @Model.PageCount  
  50.         </div>  
  51.   
  52.         @Html.PagedListPager(Model, page => Url.Action("GetBestCricketersInfo""Cricketers",  
  53.         new  
  54.         {  
  55.             page,  
  56.             currentFilter = ViewBag.CurrentFilter,  
  57.             pageSize = ViewBag.PageSize  
  58.         }),  
  59.         PagedListRenderOptions.EnableUnobtrusiveAjaxReplacing(new PagedListRenderOptions  
  60.         { 
  61.              Display = PagedListDisplayMode.IfNeeded,  
  62.              MaximumPageNumbersToDisplay = 5  
  63.         },  
  64.         new AjaxOptions  
  65.         {  
  66.              InsertionMode = InsertionMode.Replace,  
  67.              HttpMethod = "Get",  
  68.              UpdateTargetId = "CricketersGrid",  
  69.              LoadingElementId = "divProcessing"  
  70.         }))  
  71.     </div>  
  72.       
  73.     <div id="divProcessing" class="processingButton" style="display: none;">  
  74.         <img width="31" height="31" alt="" class="LoadingImage" src="~/Images/ajax-loader-round.gif" />  
  75.     </div>  
Step 19: Add the following link to the Views/Shared/_Layout Page.
  1. <li>@Html.ActionLink("Cricketers""GetBestCricketers","Cricketers")</li>  
Step 20: Build the solution and start both your projects as in the following screenshot:

Setting Multiple Startup Projects
                                     Figure 14: Setting Multiple Startup Projects

Step 21: Now run the application and click on the Cricketers:

Cricketers View
                                                Figure 15: Cricketers View

As you can see in the above screenshot that the records are displayed with the paging. Paging Numbers are based upon the total count of records and your page size defined in the"Web.Config."

Step 22:
Now click on Page No. 2 from below and you can see that the second page records will display.

Cricketers View with Paging
                                       Figure 16: Cricketers View with Paging

Note: Here every time the request is going to the database and records are fetched instead of getting whole data at first time and then perform paging on that grid. Getting whole data at one time may slow your data performance.

That’s it for the paging. Now we will proceed in the next section.

Sorting

In this section we will sort the data over ODI, Tests, ODI Runs, Tests Runs of player. We have to change the database and methods to do that. So, follow the steps below to perform that.

Step 1: Change the stored procedure from the following script:
  1. ALTER PROC[dbo].[CC_GetCricketerList]  
  2. @PageNumber INT,  
  3. @PageSize INT,  
  4. @SortExp VARCHAR(20)  
  5. AS  
  6. BEGIN;  
  7. WITH CteCricketer  
  8. AS(SELECT ROW_NUMBER() OVER(ORDER BY CASE WHEN @SortExp = 'ODI_Asc'  
  9.     THEN ODI END ASCCASE WHEN @SortExp = 'ODI_Desc'  
  10.     THEN ODI END DESCCASE WHEN @SortExp = 'Tests_Asc'  
  11.     THEN Tests END ASCCASE WHEN @SortExp = 'Tests_Desc'  
  12.     THEN Tests END DESCCASE WHEN @SortExp = 'OdiRuns_Asc'  
  13.     THEN ODIRuns END ASCCASE WHEN @SortExp = 'OdiRuns_Desc'  
  14.     THEN ODIRuns END DESCCASE WHEN @SortExp = 'TestRuns_Asc'  
  15.     THEN TestRuns END ASCCASE WHEN @SortExp = 'TestRuns_Desc'  
  16.     THEN TestRuns END DESCCASE WHEN @SortExp = ''  
  17.     THEN ID END ASC)[RowNo], * FROM dbo.CricketerProfile(NOLOCK))  
  18. SELECT CteCricketer.RowNo,  
  19.     CteCricketer.ID,  
  20.     CteCricketer.Name,  
  21.     CteCricketer.ODI,  
  22.     CteCricketer.Tests,  
  23.     CteCricketer.ODIRuns,  
  24.     CteCricketer.TestRuns, (SELECT COUNT(CteCricketer.ID) FROM CteCricketer) AS TotalCount  
  25. FROM CteCricketer  
  26. ORDER BY CteCricketer.RowNo  
  27. OFFSET(@PageNumber - 1) * @PageSize ROWS  
  28. FETCH NEXT @PageSize ROWS ONLY;  
  29. END;  
Step 2: Add the parameters in the CricketerDAL and CricketerBL as we have added in the previous section here and change the method of API from the highlighted code below:
  1. [HttpGet, ActionName("GetCricketerList")]  
  2. public HttpResponseMessage GetCricketerList(int PageNumber, int PageSize, string SortExpression)  
  3. {  
  4.     Result result;  
  5.     cricketerBL = new CricketerBL();  
  6.     try  
  7.     {  
  8.         var cricketerList = cricketerBL.GetCricketerList(PageNumber, PageSize, SortExpression);  
  9.   
  10.         if (!object.Equals(cricketerList, null))  
  11.         {  
  12.             response = Request.CreateResponse<List<CricketerProfile>>(HttpStatusCode.OK, cricketerList);  
  13.         }  
  14.     }  
  15.     catch (Exception ex)  
  16.     {  
  17.         result = new Result();  
  18.         result.Status = 0;  
  19.         result.Message = ex.Message;  
  20.         response = Request.CreateResponse(HttpStatusCode.InternalServerError, result);  
  21.     }  
  22.     return response;  
  23. }  
Step 3: Now change the CricketersController in web project from the highlighted code below: 
  1. [HttpGet, ActionName("GetBestCricketers")]  
  2. public async Task<ActionResult> GetBestCricketers(int? PageNumber, int? PageSize, string SortExpression)  
  3. {  
  4.     List<CricketerProfile> cricketersList = new List<CricketerProfile>();  
  5.     var httpClient = new HttpClient();  
  6.     httpClient.BaseAddress = new Uri(ConfigurationManager.AppSettings["ApiUrl"]);  
  7.     httpClient.DefaultRequestHeaders.Clear();  
  8.     httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));  
  9.     HttpResponseMessage response;  
  10.   
  11.     if (object.Equals(PageNumber, null))  
  12.     {  
  13.         PageNumber = 1;  
  14.     }  
  15.     if (object.Equals(PageSize, null))  
  16.     {  
  17.         PageSize = Convert.ToInt32(ConfigurationManager.AppSettings["DefaultPageSize"]);  
  18.   
  19.     }  
  20.     if (string.IsNullOrEmpty(SortExpression))  
  21.     {  
  22.         SortExpression = string.Empty;  
  23.     }  
  24.     ViewBag.PageNumber = PageNumber;  
  25.     ViewBag.PageSize = PageSize;  
  26.     ViewBag.CurrentSort = SortExpression;  
  27.   
  28.     response = httpClient.GetAsync(string.Format("api/Cricketers/GetCricketerList?PageNumber={0}&PageSize={1}&SortExpression={2}", PageNumber, PageSize, SortExpression)).Result;  
  29.   
  30.     response.EnsureSuccessStatusCode();  
  31.     var responseAsString = await response.Content.ReadAsStringAsync();  
  32.     cricketersList = JsonConvert.DeserializeObject<List<BestCricketers.Models.CricketerProfile>>(responseAsString);  
  33.     return View("~/Views/Cricketers/BestCricketers.cshtml"new CricketerInfo() { cricketerProfile = cricketersList });  
  34. }  
  35.   
  36. /// <summary>  
  37. /// This method is used to get cricketers list.  
  38. /// </summary>  
  39. /// <param name="page"></param>  
  40. /// <param name="pageSize"></param>  
  41. /// <param name="SortExpression"></param>  
  42. /// <returns></returns>  
  43. [HttpGet, ActionName("GetBestCricketersInfo")]  
  44. public async Task<ActionResult> GetBestCricketersInfo(int? page, int? pageSize, string SortExpression)  
  45. {  
  46.     List<CricketerProfile> cricketersList = new List<CricketerProfile>();  
  47.     var httpClient = new HttpClient();  
  48.     httpClient.BaseAddress = new Uri(ConfigurationManager.AppSettings["ApiUrl"]);  
  49.     httpClient.DefaultRequestHeaders.Clear();  
  50.     httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));  
  51.     HttpResponseMessage response;  
  52.   
  53.     if (object.Equals(page, null))  
  54.     {  
  55.         page = 1;  
  56.     }  
  57.     if (object.Equals(pageSize, null))  
  58.     {  
  59.         pageSize = Convert.ToInt32(ConfigurationManager.AppSettings["DefaultPageSize"]);  
  60.   
  61.     }  
  62.     if (string.IsNullOrEmpty(SortExpression))  
  63.     {  
  64.         SortExpression = string.Empty;  
  65.     }  
  66.     ViewBag.PageNumber = page;  
  67.     ViewBag.PageSize = pageSize;  
  68.     ViewBag.CurrentSort = SortExpression;  
  69.   
  70.     response = httpClient.GetAsync(string.Format("api/Cricketers/GetCricketerList?PageNumber={0}&PageSize={1}&SortExpression={2}", page, pageSize, SortExpression)).Result;  
  71.   
  72.     response.EnsureSuccessStatusCode();  
  73.     var responseAsString = await response.Content.ReadAsStringAsync();  
  74.     cricketersList = JsonConvert.DeserializeObject<List<CricketerProfile>>(responseAsString);  
  75.     return PartialView("~/Views/Cricketers/_BestCricketersPartial.cshtml"new StaticPagedList<CricketerProfile>(cricketersList, Convert.ToInt32(page), Convert.ToInt32(pageSize), cricketersList.Count > 0 ? cricketersList.FirstOrDefault().TotalCount : 0));  
  76. }  
Step 4: Now change the partial view code from the highlighted code below: 
  1. @model PagedList.IPagedList<BestCricketers.Models.CricketerProfile>  
  2. @using PagedList.Mvc  
  3.   
  4. <table class="table-responsive table">  
  5.     <thead>  
  6.         <tr>  
  7.             <th>Name</th>  
  8.             <th>  
  9.                 @Ajax.ActionLink("ODI""GetBestCricketersInfo"new  
  10.                  
  11.                   SortExpression = ViewBag.CurrentSort == "ODI_Asc" ? "ODI_Desc" : "ODI_Asc",  
  12.                   currentFilter = ViewBag.CurrentFilter,  
  13.                   pageSize = ViewBag.PageSize  
  14.   
  15.                 }, new AjaxOptions  
  16.                 {  
  17.                   LoadingElementId = "divProcessing",  
  18.                   InsertionMode = InsertionMode.Replace,  
  19.                   HttpMethod = "Get",  
  20.                   UpdateTargetId = "CricketersGrid"  
  21.                })  
  22.             </th>  
  23.             <th>  
  24.                 @Ajax.ActionLink("Tests""GetBestCricketersInfo"new  
  25.                 {  
  26.                   SortExpression = ViewBag.CurrentSort == "Tests_Asc" ? "Tests_Desc" : "Tests_Asc",  
  27.                   currentFilter = ViewBag.CurrentFilter,  
  28.                   pageSize = ViewBag.PageSize  
  29.   
  30.                 }, new AjaxOptions  
  31.                 {  
  32.                   LoadingElementId = "divProcessing",  
  33.                   InsertionMode = InsertionMode.Replace,  
  34.                   HttpMethod = "Get",  
  35.                   UpdateTargetId = "CricketersGrid"  
  36.               })  
  37.             </th>  
  38.             <th>  
  39.                 @Ajax.ActionLink("ODI Runs""GetBestCricketersInfo"new  
  40.                 
  41.                   SortExpression = ViewBag.CurrentSort == "OdiRuns_Asc" ? "OdiRuns_Desc" : "OdiRuns_Asc",  
  42.                   currentFilter = ViewBag.CurrentFilter,  
  43.                   pageSize = ViewBag.PageSize  
  44.   
  45.               }, new AjaxOptions  
  46.               {  
  47.                   LoadingElementId = "divProcessing",  
  48.                   InsertionMode = InsertionMode.Replace,  
  49.                   HttpMethod = "Get",  
  50.                   UpdateTargetId = "CricketersGrid"  
  51.               })  
  52.             </th>  
  53.             <th>  
  54.                 @Ajax.ActionLink("Test Runs""GetBestCricketersInfo"new  
  55.                 {  
  56.                   SortExpression = ViewBag.CurrentSort == "TestRuns_Asc" ? "TestRuns_Desc" : "TestRuns_Asc",  
  57.                   currentFilter = ViewBag.CurrentFilter,  
  58.                   pageSize = ViewBag.PageSize  
  59.   
  60.               }, new AjaxOptions  
  61.                
  62.                   LoadingElementId = "divProcessing",  
  63.                   InsertionMode = InsertionMode.Replace,  
  64.                   HttpMethod = "Get" 
  65.                   UpdateTargetId = "CricketersGrid"  
  66.               })  
  67.             </th>  
  68.         </tr>  
  69.     </thead>  
  70.     <tbody>  
  71.         @if (Model.Count > 0)  
  72.         {  
  73.             foreach (var cricketer in Model)  
  74.             {  
  75.                 <tr>  
  76.                     <td>@cricketer.Name</td>  
  77.                     <td>@cricketer.ODI</td>  
  78.                     <td>@cricketer.Tests</td>  
  79.                     <td>@cricketer.OdiRuns</td>  
  80.                     <td>@cricketer.TestRuns</td>  
  81.                 </tr>  
  82.             }  
  83.         }  
  84.         else  
  85.         {  
  86.             <tr>  
  87.                 <td>  
  88.                     No Data Found  
  89.                 </td>  
  90.             </tr>  
  91.         }  
  92.     </tbody>  
  93. </table>  
  94. @if (Model.TotalItemCount > Convert.ToInt32(System.Configuration.ConfigurationManager.AppSettings["DefaultPageSize"]))  
  95. {  
  96.     <div class="pagingBox">  
  97.         <input id="HiddenPageSize" name="PageSize" type="hidden" />  
  98.         <input id="HiddenPage" name="Page" type="hidden" />  
  99.         <span class="selectBoxes display_none_mobile">  
  100.             @Html.DropDownList("PageSize"new SelectList(new Dictionary<stringint> { { "10", 10 }, { "20", 20 } }, "Key""Value", Convert.ToString(ViewBag.PageSize)), new { id = "pagesizelist" })  
  101.         </span>  
  102.         <div class="pagerecord display_none_mobile">  
  103.             Records  
  104.   
  105.             Page @(Model.PageCount < Model.PageNumber ? 0 : Model.PageNumber) of @Model.PageCount  
  106.         </div>  
  107.   
  108.         @Html.PagedListPager(Model, page => Url.Action("GetBestCricketersInfo""Cricketers",  
  109.             new  
  110.             {  
  111.                 page,  
  112.                 SortExpression = ViewBag.CurrentSort,  
  113.                 currentFilter = ViewBag.CurrentFilter,  
  114.                 pageSize = ViewBag.PageSize  
  115.              }),  
  116.              PagedListRenderOptions.EnableUnobtrusiveAjaxReplacing(new PagedListRenderOptions  
  117.              {  
  118.                   Display = PagedListDisplayMode.IfNeeded,  
  119.                   MaximumPageNumbersToDisplay = 5  
  120.               },  
  121.               new AjaxOptions  
  122.               {  
  123.                    InsertionMode = InsertionMode.Replace,  
  124.                    HttpMethod = "Get",  
  125.                    UpdateTargetId = "CricketersGrid",  
  126.                    LoadingElementId = "divProcessing"  
  127.               }))  
  128.     </div>  
  129.   
  130.     <div id="divProcessing" class="processingButton" style="display: none;">  
  131.         <img width="31" height="31" alt="" class="LoadingImage" src="~/Images/ajax-loader.gif" />  
  132.     </div>  
  133. }  
Step 5: Now run the application and after opening the Cricketers page, click on the ODI link as shown below:

Perform Sorting on MVC
                                 Figure 17: Perform Sorting on MVC

When you click on the ODI link, the records will be sorted as ascending order of ODI matches

Sorting in MVC
                                                Figure 18: Sorting in MVC

Note: I have created sorting on four fields. You can change out the condition based upon your situation. In this type of sorting, whole data is not sorted. The data is sorted on that page only but when you open the next page, the database will be called again and return the data as in the sorted order because we are sending the SortExpression also.

Filtering


In this section we will filter the data over Cricketer Name. We have to change the database and methods to do that. So, follow the steps below to perform that.

Step 1: Change the stored procedure from the following script:
  1. ALTER PROC[dbo].[CC_GetCricketerList]  
  2. @PageNumber INT,  
  3. @PageSize INT,  
  4. @SortExp VARCHAR(20),  
  5.     @SearchText NVARCHAR(150)  
  6. AS  
  7. BEGIN;  
  8. WITH CteCricketer  
  9. AS(SELECT ROW_NUMBER() OVER(ORDER BY CASE WHEN @SortExp = 'ODI_Asc'  
  10.     THEN ODI END ASCCASE WHEN @SortExp = 'ODI_Desc'  
  11.     THEN ODI END DESCCASE WHEN @SortExp = 'Tests_Asc'  
  12.     THEN Tests END ASCCASE WHEN @SortExp = 'Tests_Desc'  
  13.     THEN Tests END DESCCASE WHEN @SortExp = 'OdiRuns_Asc'  
  14.     THEN ODIRuns END ASCCASE WHEN @SortExp = 'OdiRuns_Desc'  
  15.     THEN ODIRuns END DESCCASE WHEN @SortExp = 'TestRuns_Asc'  
  16.     THEN TestRuns END ASCCASE WHEN @SortExp = 'TestRuns_Desc'  
  17.     THEN TestRuns END DESCCASE WHEN @SortExp = ''  
  18.     THEN ID END ASC)[RowNo], * FROM dbo.CricketerProfile(NOLOCK) WHERE Name LIKE '%' + @SearchText + '%')  
  19. SELECT CteCricketer.RowNo,  
  20.     CteCricketer.ID,  
  21.     CteCricketer.Name,  
  22.     CteCricketer.ODI,  
  23.     CteCricketer.Tests,  
  24.     CteCricketer.ODIRuns,  
  25.     CteCricketer.TestRuns, (SELECT COUNT(CteCricketer.ID) FROM CteCricketer) AS TotalCount  
  26. FROM CteCricketer  
  27. ORDER BY CteCricketer.RowNo  
  28. OFFSET(@PageNumber - 1) * @PageSize ROWS  
  29. FETCH NEXT @PageSize ROWS ONLY;  
Step 2: Add the parameters in the CricketerDAL and CricketerBL and change the method of API from the highlighted code below: 
  1. [HttpGet, ActionName("GetCricketerList")]  
  2. public HttpResponseMessage GetCricketerList(int PageNumber, int PageSize, string SortExpression, string SearchText)  
  3. {  
  4.     Result result;  
  5.     cricketerBL = new CricketerBL();  
  6.     try  
  7.     {  
  8.         var cricketerList = cricketerBL.GetCricketerList(PageNumber, PageSize, SortExpression, SearchText == "undefined" ? string.Empty : SearchText);  
  9.   
  10.         if (!object.Equals(cricketerList, null))  
  11.         {  
  12.             response = Request.CreateResponse<List<CricketerProfile>>(HttpStatusCode.OK, cricketerList);  
  13.         }  
  14.     }  
  15.     catch (Exception ex)  
  16.     {  
  17.         result = new Result();  
  18.         result.Status = 0;  
  19.         result.Message = ex.Message;  
  20.         response = Request.CreateResponse(HttpStatusCode.InternalServerError, result);  
  21.     }  
  22.     return response;  
  23. }  
Step 3: Now change the CricketersController in web project from the highlighted code below: 
  1. public async Task<ActionResult> GetBestCricketers(int? PageNumber, int? PageSize, string SortExpression, string SearchText)  
  2. {  
  3.     List<CricketerProfile> cricketersList = new List<CricketerProfile>();  
  4.     var httpClient = new HttpClient();  
  5.     httpClient.BaseAddress = new Uri(ConfigurationManager.AppSettings["ApiUrl"]);  
  6.     httpClient.DefaultRequestHeaders.Clear();  
  7.     httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));  
  8.     HttpResponseMessage response;  
  9.   
  10.     if (object.Equals(PageNumber, null))  
  11.     {  
  12.         PageNumber = 1;  
  13.     }  
  14.     if (object.Equals(PageSize, null))  
  15.     {  
  16.         PageSize = Convert.ToInt32(ConfigurationManager.AppSettings["DefaultPageSize"]);  
  17.   
  18.     }  
  19.     if (string.IsNullOrEmpty(SortExpression))  
  20.     {  
  21.         SortExpression = string.Empty;  
  22.     }  
  23.     if (string.IsNullOrEmpty(SearchText))  
  24.     {  
  25.         SearchText = "undefined";  
  26.     }  
  27.     ViewBag.PageNumber = PageNumber;  
  28.     ViewBag.PageSize = PageSize;  
  29.     ViewBag.CurrentSort = SortExpression;  
  30.   
  31.     response = httpClient.GetAsync(string.Format("api/Cricketers/GetCricketerList?PageNumber={paging-sorting-and-filtering-with-partial-view-in-Asp-Net-m}&PageSize={1}&SortExpression={2}&SearchText={3}", PageNumber, PageSize, SortExpression, SearchText)).Result;  
  32.   
  33.     response.EnsureSuccessStatusCode();  
  34.     var responseAsString = await response.Content.ReadAsStringAsync();  
  35.     cricketersList = JsonConvert.DeserializeObject<List<BestCricketers.Models.CricketerProfile>>(responseAsString);  
  36.     return View("~/Views/Cricketers/BestCricketers.cshtml"new CricketerInfo() { cricketerProfile = cricketersList });  
  37. }  
  38.   
  39. /// <summary>  
  40. /// This method is used to get cricketers list.  
  41. /// </summary>  
  42. /// <param name="page"></param>  
  43. /// <param name="pageSize"></param>  
  44. /// <param name="SortExpression"></param>  
  45. /// <returns></returns>  
  46. [HttpGet, ActionName("GetBestCricketersInfo")]  
  47. public async Task<ActionResult> GetBestCricketersInfo(int? page, int? pageSize, string SortExpression, string SearchText)  
  48. {  
  49.     List<CricketerProfile> cricketersList = new List<CricketerProfile>();  
  50.     var httpClient = new HttpClient();  
  51.     httpClient.BaseAddress = new Uri(ConfigurationManager.AppSettings["ApiUrl"]);  
  52.     httpClient.DefaultRequestHeaders.Clear();  
  53.     httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));  
  54.     HttpResponseMessage response;  
  55.   
  56.     if (object.Equals(page, null))  
  57.     {  
  58.         page = 1;  
  59.     }  
  60.     if (object.Equals(pageSize, null))  
  61.     {  
  62.         pageSize = Convert.ToInt32(ConfigurationManager.AppSettings["DefaultPageSize"]);  
  63.   
  64.     }  
  65.     if (string.IsNullOrEmpty(SortExpression))  
  66.     {  
  67.         SortExpression = string.Empty;  
  68.     }  
  69.     if (string.IsNullOrEmpty(SearchText))  
  70.      
  71.         SearchText = "undefined" 
  72.     }  
  73.     ViewBag.PageNumber = page;  
  74.     ViewBag.PageSize = pageSize;  
  75.     ViewBag.CurrentSort = SortExpression;  
  76.   
  77.     response = httpClient.GetAsync(string.Format("api/Cricketers/GetCricketerList?PageNumber={paging-sorting-and-filtering-with-partial-view-in-Asp-Net-m}&PageSize={1}&SortExpression={2}&SearchText={3}", page, pageSize, SortExpression, SearchText)).Result;  
  78.   
  79.     response.EnsureSuccessStatusCode();  
  80.     var responseAsString = await response.Content.ReadAsStringAsync();  
  81.     cricketersList = JsonConvert.DeserializeObject<List<CricketerProfile>>(responseAsString);  
  82.     return PartialView("~/Views/Cricketers/_BestCricketersPartial.cshtml"new StaticPagedList<CricketerProfile>(cricketersList, Convert.ToInt32(page), Convert.ToInt32(pageSize), cricketersList.Count > paging-sorting-and-filtering-with-partial-view-in-Asp-Net-m ? cricketersList.FirstOrDefault().TotalCount : paging-sorting-and-filtering-with-partial-view-in-Asp-Net-m));  
  83. }  
Step 4: Now change the Main view (BestCricketers.cshtml) code from the highlighted code below: 
  1. @using (Ajax.BeginForm("GetBestCricketersInfo""Cricketers"nullnew AjaxOptions() { LoadingElementId = "divProcessing", HttpMethod = "Get", UpdateTargetId = "CricketersGrid" }, htmlAttributes: new { @id = "cricketerInfo" }))  
  2. {  
  3.     <div id="SearchCricketer" style="float:right;">  
  4.         <input type="text" class="form-control" id="TxtSearchCricketer" placeholder="Search" />  
  5.     </div>  
  6.     <div class="clearfix"></div>  
  7.     <div id="CricketersGrid">  
  8.         <div id="divProcessing" class="processingButton" style="display: none;" 
  9.             <img width="31" height="31" alt="" class="LoadingImage" src="~/Images/ajax-loader.gif" />  
  10.         </div>  
  11.         @Html.Partial("~/Views/Cricketers/_BestCricketersPartial.cshtml"new StaticPagedList<BestCricketers.Models.CricketerProfile>(Model.cricketerProfile, Convert.ToInt32(ViewBag.PageNumber), Convert.ToInt32(ViewBag.PageSize), Model.cricketerProfile.Count > paging-sorting-and-filtering-with-partial-view-in-Asp-Net-m ? Model.cricketerProfile.FirstOrDefault().TotalCount : paging-sorting-and-filtering-with-partial-view-in-Asp-Net-m))  
  12.     </div>  
  13. }  
  14.   
  15. <script type="text/javascript">  
  16.     var timer;  
  17.     $("#TxtSearchCricketer").on('keyup', function (event) {  
  18.         clearTimeout(timer);  //clear any running timeout on key up  
  19.         timer = setTimeout(function () { //then give it a second to see if the user is finished  
  20.             $.ajax({  
  21.                 url:'@Url.Action("GetBestCricketersInfo","Cricketers")' 
  22.                 dataType:"html" 
  23.                 data:{page:@ViewBag.PageNumber,pageSize:@ViewBag.PageSize, SortExpression:'@ViewBag.CurrentSort', SearchText:$('#TxtSearchCricketer').val()},  
  24.                 type:"Get" 
  25.                 success: function (data) {  
  26.                     $("#divProcessing").hide();  
  27.                     $('#CricketersGrid').html(data);  
  28.                 },  
  29.                 beforeSend: function () {  
  30.                     $("#divProcessing").show();  
  31.                 }  
  32.             })  
  33.         }, 5paging-sorting-and-filtering-with-partial-view-in-Asp-Net-mpaging-sorting-and-filtering-with-partial-view-in-Asp-Net-m);  
  34.     });  
  35. </script>  
Note: I have created an Ajax call to perform the filtering in MVC grid. You can apply any other procedure to call the Action in Controller.

Step 5: Now run the application and you can see the Search Textbox.

Filtering in MVC
                                                Figure 19: Filtering in MVC

Enter the name to filter the records.

Filtered Records in MVC
Figure 20: Filtered Records in MVC

Summary

So far this article describes hpw to perform Paging, Sorting, and Filtering with the help of Partial Views in the ASP.NET MVC Application. You also learned the use of PagedList in View and Partial view. Thanks for reading this article. Happy coding! 
 
Read more articles on ASP.NET:

Up Next
    Ebook Download
    View all
    Learn
    View all