SEARCH IN ASP.NET CORE

LEVERAGE MODEL BINDING TO RECEIVE USER INPUT

NET CORE

Now we are going to look at a very important part which is how to receive input from our users. Let’s start by talking about model binding which is a convention-based mechanism that is very simple and intuitive to use that allows us to collect user input and use it in the Actions of our Controllers.

Model binding

As we said model binding is based on conventions, instead of id we could choose another name, the important thing is that the template name matches the parameter name. Let’s give examples.

Model binding

The five is extracted thanks to the RouteValueProvider and this information in text format is converted to an integer by the SimpleTypeModelBinder.

Model binding
Model binding

The ComplexTypeModelBinder not only creates the object but also values its properties. If a request comes to Courses, the QueyStringValueProvider will not know how to do the binding with the Action parameters, in these cases we can provide default values.

Valori di default

Id will take the value four in this ambiguity.

Attributi Form
Attributi form

CREATE THE SEARCH FORM

Let’s dust off the specification.

Specifica

Let’s look at the plan to implement the research.

Ricerca

Let’s look at a summary slide on the Form tag.

Tag Form
GET E POST

This is the code for the View.

Index

IMPLEMENT SEARCH FUNCTIONALITY

A couple of points we already fixed using naming conventions and model binder, let’s see the slide.

Ricerca

All we have to do is provide this key to the application services so that they can offer us courses relevant to the research. Let us first modify the AdoNetCourseService class.

AdoNetCourseService

It could be made so that when no text is typed, the WHERE clause is not inserted. It is actually the Query Optimizer that does this work for us.

Query Optimizer

Now we go on to complete the other Application service, EfCoreCourseService.

EfCoreCorseService

SUMMARY

ASP.NET Core has a mechanism called model binding that takes care of examining the HTTP request to extract useful information so that we can then use it in our controller actions. It consists of two main organs:

  • The value providers take care of extracting the raw values, in string format, from the various parts of the request such as route parameters, query string, form data, and headers;
  • Model binders, on the other hand, take care of converting those raw values into the data types that have been expressed as parameters of the action.

Here, for example, is a query in which a query string page key valued at 5 was provided.

https://localhost:5001/Courses?page=5

And here is the action that will handle that request, which will receive the value 5 from its page parameter of type int.

  1. public ActionResult Index(int page)
  2. {
  3. //…
  4. }

Without us having to do anything, the value 5 was retrieved from the query string thanks to a value provider and then converted to the int type by a model binder.

Model binders are very powerful and can create both objects of primitive types (such as int and bool) as well as complex types, such as custom classes we create. This last aspect is very important, especially when we will be making editing masks, because it allows us to keep so many values cohesive in one object.

The model binding mechanism uses naming conventions, which is why the value supplied with a querystring key called page can arrive at an action parameter also called page. The comparison is done in a case-insensitive manner.

There can be name collisions in a query that can lead to ambiguity, such as a query string key called page and a form field also called page. In this case we can use attributes to be explicit about the source to be used to derive the value. Here is an example where we use the FromQuery attribute at the page parameter to indicate that the value should be taken from the query string.

  1. public ActionResult Index([FromQuery] int page)
  2. {
  3. //…
  4. }

Here is a list of attributes we can place next to the action parameters:

  • FromForm draws from values submitted with a form (POST method);
  • FromRoute from the parameters given in the route template (for example, the id given in {controller}/{action}/{id});
  • FromQuery from the query string keys;
  • FromHeader from the HTTP request headers. It is necessary to use it if we want to draw values from there;
  • FromServices does not draw values from the request but from objects registered for dependency injection.

LINK TO CODE ON GITHUB

GITHUB

Download the section13 code or clone the GITHUB repository to have all sections available in your favorite editor.