DEV Community

Cover image for Understanding Model Binding in ASP.NET
Panji Kristi Prawiro
Panji Kristi Prawiro

Posted on

Understanding Model Binding in ASP.NET

Introduction

HTTP is the backbone of a website's communication. This regulates how clients and servers exchange information. One of the must-have capabilities of a server is to get data from a client's request. In ASP NET Core, every incoming request from the client will be caught by the Kestrel server and transformed into object context, then passed into source code, and finally routed to the endpoint. First, let's look at how to get data from request object context without a model binding mechanism.

Get query string from context object
Send request with query string

Watch extracted query strings

Without model binding, you must do extra work to do. First, you need to access the IQueryCollection object from HttpContext and check if there is any associate key-value pair. If any, it will give you a StringValues type, which under the hood implements IList<string> so you need to access a string element from that list, and then you need to perform a type conversation from the string into the appropriate value. This tedious work increases the error-proneness, luckily ASP.NET offers the easy way with Model Binding mechanism. 

Model Binding

Model binding is one of the greatest mechanisms in ASP.NET. It is a process of collecting the data from an incoming request (it could be in the form of query string, route data, request body, or request header) and then supplying the values as an action method argument. Hence, you have access directly to data that was sent from the client to perform validation and process it in the business logic layer. Behind the scenes, ASP.NET will take care of the binding process, so it's not ours. The model binding mechanism will automatically perform when requests are routed to match endpoints and right before the execution of the action method.

Model Binding Mechanism Illustration perform between incoming request and execution of action method

let's look how to get query string data with model binding
Send request with query string


Watch value of variable

It seems like magic 🎩✨🐇 isn't it?

It is significantly quicker and easier. to extract data from a query with model binding that you wouldn't need to perform a data conversation from a string into an appropriate type. It comes automatically behind the scenes by model binding.

In order to bind successfully, you must make sure the name of the key of the query string matches the identifier of the action method parameter. but you don't have to match the case because it is not case-sensitive. Bonded data is not limited to one source. It still works fine if you place the data in the query string and route data.

Get Query String and Route Data with model binding

postman send request with query string and route data


Watch value of variable

So it is great that ASP.NET has these features to make development more intuitive, easy, and fast. However, if you don't understand the behavior of model binding, you will end up confused. Let's say the client makes the following request: 

Send Request with route data and query string
Watch value of variable

From above, we can see that it has collision data between the query string and route data because they have the same identifier called "movieId". If we look at the above watch window, the movieId gets populated with a value of 89. You might wonder why ASP.NET extracts "movieId" parameter data from route data instead of a query string? It turns out ASP.NET has an order of priority for model binding. Let's take a look at the image below, It starts from the top, which has the highest priority, down to the bottom, which has less priority.

Model binding priority

Great, now you have a better understanding of model binding behavior.
But what if you don't want to achieve this behavior?
You can use the [FromQuery] attribute to tell ASP.NET, "Hey, forget about your order priority. I will state explicitly that I want you to bind the data from the query string instead."


watch variable value
It will populated movieId with value of 22 instead of 89.

here another useful attribute list that you can use to explicitly specify the source of data for action method parameters

  • [FromRoute]
  • [FromQuery]
  • [FromBody]
  • [FromForm]

Model Binding with Model Class

What happens if the customer provides a lot of data? Of course, you don't want to scatter up the action method arguments; it will clutter your code. Instead,  you can create a model class and declare it as an action method parameter. Model binding will automatically map incoming request data to the properties of your model class based on their names.

client send a request with a multipart/form-data content type

send request upload movie


watch movie property value

Great, the movie object has been automatically populated based on the data from the request form-data. Sometimes you want more granular control over which properties get populated from incoming request data, to achieve this, you can utilize [Bind] and [BindNever]attributes.

  • Bind

    decorate action method parameter with Bind attribute then you need to supply name of property or parameter to include in binding. It will tell that we only interest to populate Title value and leave the rest of properties to hold null or default value
  • BindNever

    decorate the property model that you want to exclude from the model binding process. It will make the Title property excluded from the binding process hence, it will store a null value, and the rest of the properties still be populated from the binding.

Custom Model Binders

ASP.NET gives you more control over the binding process from requests into action method parameters by creating your own model binding class. so it will override the built-in Model binding mechanism and use your own model binding class. Let's say that the client will send query string data of poster URL and trailer URL and you want to store them into a single value separated by semicolon. First, you need to create a class that implements the IModelBinder interface and overrides the BindModelAsync method.

After you create your own model binder class, you need to decorate the parameter of your model parameter in the action method with the ModelBinder attribute and pass your model as a type on the first argument.

send request with posterUrl and trailerUrl data

Watch window value of movie with custom model binder

You are successfully using your own custom model binder so you can have granular control over the rule of the binding process.

Conclusion

Model Binding Mechanism in ASP.NET helps us to populate data from requests with a breeze. It will perform automatically, and you don't have to write tedious code that could be error-prone. With the understanding behavior of model binding performed by ASP.NET you know how to handle it if something looks off or does not look as you expect it with the right technique. Even if the model binding by ASP.NET cannot meet your requirements, you can create your custom model binders by yourself and override the built-in model binding mechanism in ASP.NET.

Top comments (1)

Collapse
 
jwp profile image
John Peters

Nice