There are a ton of different ways to accomplish sorting, paging, and searching but here is how we've been doing it lately with ASP.NET MVC 5 in C# with Entity Framework 6.
We use a few different components to achieve the sorting and pagination. First is a NuGet package called PagedList.MVC. This gets us quite far on the paging front as it includes an HtmlExtension that will generate the pager UI out of the box. It does require some minor modification of your code however as the view's model will now need to be of the type
instead of an Enumerable list of the object type. On the controller action side, you'll need an IOrderedQueryable to pass into the ToPagedList extension method which means you might need to refactor your data access services if they had previously been returning an executed query. It's important to note that your LINQ statement must have an OrderBy clause or the ToPagedList method will fail.
Next we have a couple of extension methods we've created to help us out with our sorting and searching parameters and UI. One method is used to apply the up or down chevron style to the TH element based on which direction it's column is being sorted. The other is used to persist any URL parameters and optionally append a new parameter, in this case a new sort identifier:
That does it for the parts that make up the solution. Next we just put them together with our code.
Our Razor view uses a normal HTML table element and a model of IPagedList to iterate through. Your model could contain this list as a portion of a larger view model. We build our table followed by the PagedList library's pagination HtmlExtension to present the pager controls.
You'll notice that the top of the view gets a handle on the current sort and search values so that they can be applied or carried through additional requests. The default sort value is also set if none were previously set.
In the table head, we use our two extension methods to generate the sort links for each table header and also determine the sort UI if necessary for any currently sorted column.
After the table, we call the PagedList extension method to generate the pager controls based on our data collection. It also allows us to pass in extra route data which we are using to include the current page, a search term, and a sort order.
With the view ready, we need to hook up our controller to actually perform the work. We use a single action in this example but you could use a few depending on how you want to tackle it.
You'll need to swap in your actual data call where I have the DataService and your actual table columns of course, but the code should be pretty straight forward. Grab the search query,page and page size, determine the sort order and if it should be ascending or descending, then build the query using the search term before finally sorting it and supplying the query to the ToPagedList extension for use in the view model.
If anyone is accomplishing this task in a better way, tell me about it. This works well but can be error prone with the variable names in the view and controller. You could use this same technique but create search view models for each table which would allow you to strongly type the variables instead and reduce error.