Loading...
...
Posted by Firuza Polad on June 27, 2025

Model Binding

Model Binding is the process of automatically mapping HTTP request data (eg: from input, query string etc), to action method parameters or .NET object. It simplifies development by abstracting the parsing HTTP data and letting to focus on BL. Eg; when a client sends data in a request, the model binding automatically translate data into strongly typed object. There are some resources that model binding use for:
Query String [FromQuery]: Used when data is sent via URL query string (?name=John). Ideal for simple types and filters, paginations in GET request.
Route Data [FromRoute]: Used to bind parameters from URL path (/users/5). Useful for ID and values defined in route.
Form Data [FromForm]: Used for APIs that receive JSON payloads, like POST/PUT. files
Request Body [FromBody]: Used when raw body content we have, usually JSON and maps it complex types. Only one parameter is allowed per action, means we can not have more than one parameter with FromBody like:
PostUser([FromBody] UserDto user, [FromBody] AddressDto address) Because if we send multiple parameter and during deserialize into objects, the framework wouldn't know how to split them.
Headers [FromHeader]: Used for authentication token, and binds value from Http header.
Default Binding (No Attribute): When no attribute (like above) is used , then frameworks choose the source automatically based on parameter type. So, simple types like int, string, bool, datetime bind from Route, QueryString, Form source.
Eg1: public IActionResult GetUser(int id){//your code} Comes from /GetUser?id=7. Complex types (classes) bind from request body,
Eg2: public IActionResult GetUser(UserDto user){//your code} except JSON in the body like {"name":{Firuza}}

Custom Model Binding

Normally, .NET takes data from the request and automatically fills our object, this process is called model binding. But if the data comes from multiple places like part of URL and part of body or comes from in a weird format, then the default binding may not work, in this situation Custom Model Binding lets us write our own rules for how to handle request data and turn it our object. We use it to bind data from non-standart request format; to combine multiple input sources into one model. How to use?

  • - Create class that implement IModelBinder
  • - Create ModelBinderProvider
  • - Decorate model with [ModelBinder] attribute

Eg: Lets say user sends date in format "dd-MM-yyyy" from the query string (like ?dob=26-06-2025), but by default we expects something "yyyy-mm-dd" like 2025-06-26. So if user send 26-06-2025 then model binding fails. To solve it we override the excepted format, we convert it into valid DateTime object, even if system except yyyy-mm-dd, code will work without client needing change their format. (see below image)

Model Validation

After model binding occurs, to track the validity of model binding, like to check if incoming data is valid according to our model we use it. Used in controller actions and will contain the errors.
Firstly lets see what are validations- it refers to the process used to ensure that data entered by user is correct before it stored. Key concepts & Types of Validation:

  • - Data Integrity: Ensuring data is correct
  • - User Experience: Providing clear feedback to users
  • - Security: Protect application from attacks

  • - Client-side: it validate data in user's browser before submitting, like using script language, user input is validated in browser before sending to server. If there is an invalid email format then provide immediate feedback.
  • - Server-side: it validate data on server, like using c#/Java/Python, and ensure security after form is submitted, it is more secure than client-side validation. Validate more complex BS rules, prevent attacks like SQL injection.
  • - Database: it enforce data in DB level, like defining constraints in DB. Ensure data consistency through system, like value of username are not duplicated, or specific rules on columns.

Data Annotations: are provide validation on client-side and server-side by using attributes directly on model properties. Simplifies code logic, ensure validation applied same for client and server. It has a range of built-in attributes like below and besides we can also create Custom Data Annotations.

  • [Required]: Mark a field as required
  • [MinLength] & [MaxLength]: indicate min and max length for string properties: [MinLength(4)]
  • [StringLength]: set max and min for string at the same time, like [StringLength(7,MinimumLength=4)]
  • [Range(4,7)]: get values between specified range
  • [EmailAddress]: validate property that has a valid email format
  • [RegularExpression]: ensure that propery match with given expression pattern
  • [DataType(typeName)]: specify data type like Date,Time,Email

Data Transfer Objects (DTO)

Are used to encapsulate and transfer data between layers of application, like between UI layer, Service layer and Data Access Layer. Ensure clean separation by reducing unnecessary data from external system like APIs. So we can say it is a simple container without BS logic. To use it, we defining domain model which represent how data is reftected in DB, then creating a DTO for exclude sensitive fields, and then we map data manually (to simplify it we use AutoMapper later). Generally we create seperate DTO for different operations, like for create operation CustomerCreateDTO (write/update) - exclude sensitive data like passwords, for fetch operation CustomerGetDTO(read-only) - include sensitive data if needed like Price,AdminNote.


AutoMapper

As earlier article I mentioned that there are different layers for application, where each layer has its own representation of data. DAL, BL, Application Layer, and converting data between models and Dto especially if application grows can be problem. So, Automapper is an open-source object-to-object mapping library , used to convert object of one type to another type automatically. Commonly used to simplifying conversion between different layers of application, instead manual conversion code between DTO and domain models or vice versa. Lets start what is Model?- It indicate data structure in DB and map data directly to DB table. And every field needs to store data.
Eg: we have Customer model and customerDTO, we can define mapping between these objects. We use TSoruce- object we are mapping From, TDestination-we are mapping To. We use ForMember() and MapFrom() to customize how one property mapped to another when property names don't match or need changes, Eg; we map 'Name' as 'UserName' or vice vers (see MappingProfile.cs)
Map configuration: - Install NuGet packages in the project; (AutoMapper,DependencyInjection);
- Creating AutoMapper Profiles between two models;
- Use the AutoMapper instance (IMapper) to perform mapping;
CreateMap<TSource,TDestination>(); used to define mapping for all instances. For all Create operations, all Get operations.
CreateMap<CustomerDTO, Customer>(); // Mapping for create operations
CreateMap<Customer, CustomerDTO>(); // Mapping for get/retrieve operations

Mapping From DTO to Domain: var customer = mapper.Map<Customer>(customerDTO); In here CustomerDTO (TSource) is data we get from external system like user input, and Customer (TDestination) is domain model we want to populate from DTO, used in create operation. AutoMapper generates a new instance of Customer from customerDTO, customerDTO provides all the necessary data.
Mapping from Domain to DTO: var customerDTO = mapper.Map<CustomerDTO>(Customer); means mapping from domain model to DTO. It is used when getting data from DB, and mapping it to DTO to return back to client. The Customer object provides the source data, and AutoMapper creates a new instance of CustomerDTO for you.
Using Map<TSource, TDestination>(sourceObj)- is optional syntax, if we want to use CreateMap<TS,TD> syntax also for Map<TD>(TS), then we use instance object like: Map<Customer,CustomerDTO>(customers); and this same with Map <CustomerDTO>(Customer);
Update Existing Object: var updatedCustomer = _mapper.Map(updateDto, Customer); means we are working with existing Customer object, and applying changes from DTO to existing object. It wont create new Customer object, update existing one.

Below image, without AutoMapper PROBLEM : we will get the output as expected. But if the data ( e.g . properties) are increased then mapping is repeated between the source and the destination

Information
All diagrams, Folder structure, Code example in this blog were created by me using Lucid , Canva and IDE If you'd like to contribute, request more diagrams or text, or suggest improvements, feel free to contact me
© 2025 Firuza Polad. All rights reserved.

Let’s Connect

I’m open to collaboration, remote and freelance work!