Most sorting examples show how to pass the column header to C# code that uses a
switch statement to build a LINQ query:var query = context.SomeData;
switch(columnHeader)
{
case "ID":
query = query.SortBy(c => c.ID);
break;
case "FullName":
query = query.SortBy(c => c.FullName);
break;
// etc
}
This works but it suffers from 3 limitations:
- It can require a lot of code, especially if I also want to allow the user to specify the sort direction too.
- It is not reusable. I can't use this code block with a different data set because it is dependent on the columns in the result set.
- It is not particularly scalable. If I want to add or remove columns, I have to modify the
switchstatement which could result in the introduction of bugs.
A really neat solution to this is the Dynamic Linq library. It provides extension methods such as
OrderBy that take string arguments instead of type-safe expressions. It means that I don't have to know the shape of the model that the OrderBymethod acts upon at design time. It is evaluated dynamically at runtime. This was originally released by Microsoft, but not as part of the .NET Framework. It has since been ported to .NET Core by a few people, one example of which can be found here: https://github.com/StefH/System.Linq.Dynamic.Core. I can install it using Nuget:install-package System.Linq.Dynamic.Core
Or I can use the command line:
dotnet add package System.Linq.Dynamic.Core
Once it is available to the application, I add another method to the
PersonService from the previous article. Here it is again in its entirety with its interface:
The addition is the version of the
GetPaginatedResult method that takes a string representing the column to sort by. I need to change the OnGetAsync method in the PageModel to call this method, and I need to add a property to the PageModel to represent the column to sort by. Here is the revised PageModel class:
One other change to note - I removed the default value for the
CurrentPage property. I am going to move that to the page's route template instead, and add another parameter for sortby:@page "{currentpage=1}/{sortby=Id}"
The only thing left to do now is to add column headers to the table with hyperlinks to specify the sort order, and to adjust the paging links. Here is the revised content page:
The
thead element contains the column headers with the links. The links themselves are generated by anchor tag helpers. Each one has an asp-route-sortby attribute set to the value of the respective column. This will ensure that the correct value is provded to the RouteData dictionary, from where it will be bound to the SortBy property in the PageModel. The value for the currentpage parameter will be supplied from ambient route values.
The revised paging links at the bottom of the code include values for both the
currentpage and the sortby parameters. The currentpage value is set explicitly, which has the effect of negating all subsequent ambient route values, so thesortby value must also be set explicitly.
Now when you click one of the sorting links, the paging links also include the sorting information:

No comments:
Post a Comment