PAGINATION IN ASP.NET CORE
We need to limit the number of courses displayed per page; extracting ten courses from the database will be extremely faster than extracting a thousand. Let’s look at the plan to implement pagination.
Let’s add Bootstrap 5.3 pagination links
Let’s look at the Tag Helper generated by asp-route-page.
Let’s see how to perform pagination with SQL dialect with a slide. LIMIT is equal to ten because each page must contain ten results, OFFSET twenty because we want to get the third page; therefore, we have to skip the first 20 results.
Let’s see how paging is done with LINQ.
SORT THE RESULTS INTO THE LIST
Let’s see the plan to implement sorting, on pagination we will return later. Apart from having two parameters orderby and ascending the rest changes little.
Let’s see how to use the ORDER BY clause in the SQL dialect. When there is no indication, the default value is ASC (ASCENDING)
There are some issues in the ordering that I report in the slide. First, orderby needs to be sanitized, ascending is a bool while we need the strings ASC and DESC. orderby and ascending cannot become SqliteParameters, so I created a Sql.cs class.
Let’s see if we can fix all these issues in the code. Instead of ascending we put direction which takes ASC and DESC values as desired. If we don’t get a correct orderby value we sanitize it and use the defaults defined in the configuration in the appsettings.json file.
Let’s look at sorting with LINQ.
CREATE A CUSTOM MODEL BINDING
After implementing a feature, it is necessary to look back and see if the code can be improved. This activity is called Refactoring and it is necessary to do it because writing code is a complex activity, already arriving at a solution requires some effort. For example, after implementing these three features, I realize that sanitization has been placed within the application services, and this is wrong because right now these services are burdened with an extra responsibility, whereas they should only be deciding what to pull from the database.
SANITIZATION
If sanitization had been done more upstream, that is, when the user enters values perhaps using a custom model binding perhaps that would have been the right solution. Let us first see where the problem lies by looking at the AdoNetCourseService class.
The sanitization logic in this class is duplicated in the other application service EfCoreCourseService and this is wrong. One possible solution is to create a class that takes care of sanitizing values and center this whole part in one place.
The problem with this new class is that having removed the setters to the properties, this is because we don’t want these values to be changed externally even accidentally, the model binder no longer works. We have to build our own model binder.
This is the code for the CourseListInputModelBinder class.
EXPLANATION OF THE MODEL BINDER
The“BindModelAsync” method is defined in the“CourseListInputModelBinder” class, which implements “IModelBinder” interface. This class is a custom binding tool, used by ASP.NET Core to associate HTTP request data with Action parameters. In this method, `bindingContext.ValueProvider` provides values from the HTTP request Request data are retrieved and transformed into appropriate types. Therefore, a new instance of `CourseListInputModel` is created with this data.
COURSE LIST INPUT MODEL INSTANCE CREATION
This new instance is then set as a result for the association context to indicate that the model has been associated correctly. Finally, the method returns “Task.CompletedTask” because it is an asynchronous method, but in this case no actual asynchronous work is performed. Finally, this custom template binder is used in the class “CourseListInputModel” using the “ModelBinder” attribute. Therefore, when ASP.NET Core detects a parameter of type “CourseListInputModel” in an Action, it will use “CourseListInputModelBinder” to associate the HTTP request data with that parameter.
KEEP THE STATE IN THE VIEWS
Razor views lose memory from one request to the next, currently if we type some search string in the text box at submit the typed text is lost. Now we are going to see how our HTML elements maintain a consistent state across various user requests.
If the user typed Guitar in the search box this value via the Custom Model Binder gets to the controller involving the View to extract courses relevant to the search criteria. However, the View is not aware of what the user typed in, nor of the sorting criteria and pagination links. Let’s see how to solve the problem.
In a View we cannot use multiple @model directives but we can encapsulate in a new Model all the properties we need, including user input, and provide this new class as @model.
Now as a model in the Course Index page we will use CourseListViewModel which contains all the information we need. Let’s see how we have valued the properties in the Controller. Refer to the View Razor Index code to see how I maintained the state.
MAKE PAGINATION LINKS DYNAMIC
To implement pagination links we need to know the number of total rows of the courses, which the controller is not returning. Instead of a List<CourseViewModel> which is what the Controller is currently returning to us we need a new class ListViewModel<CourseViewModel> to keep track of the number of total records searched in the text box, or all if left blank. Download the source code and look at the implementation of this new class in the controller and application services.
LINK TO CODE ON GITHUB
Download the section13 code or clone the GITHUB repository to have all sections available in your favorite editor.
Leave A Comment