COMPUTER ENGINEER

Jump to examples
Blog
Next.js / ASP.NET Core / SQL6 min study
17/ 41

The ASP.NET Core pipeline

Model binding: from HTTP to C# objects

How route, query string and body become method parameters, and how over-posting is prevented.

UnderstandStudy an examplePractise

Understand the concept

Model binding converts values from different parts of the request into method parameters. Route values and the query string bind to simple types; a JSON body binds to complex types. With [ApiController], complex types are read from the body by default; [FromRoute], [FromQuery], [FromBody] and [FromHeader] name the source explicitly.

Type conversion happens during binding. If ‘abc’ cannot bind to an int parameter, an error is added to ModelState and [ApiController] rejects the request with 400 automatically. The JSON body is read with System.Text.Json and its size can be limited.

The most important security rule: never make a database entity the binding target. A user can add unexpected fields to the body (IsAdmin, Price, OwnerId) and they all get written to the entity; this is over-posting or mass assignment. Use a request model (DTO or record) containing only the permitted fields instead.

WHEN TO USE IT

Every value from the request is untrusted input; where it comes from and in what shape must be explicit.

COMMON PITFALL

Binding an EF Core entity with [FromBody] and calling SaveChanges directly.

LIVE ANIMATION

A letter’s journey through the city

Think of a request as a letter and the server as a city. Pick a scenario, press play and watch which gates the letter passes and where it gets stopped.

CLIENTEDGEWEB SERVERAPI · ASP.NET COREDATABrowserThe user’s screenNetworkDNS · TCP · TLSReverse proxyTLS termination, compressionNext.js serverSSR and route handlersKestrelHTTP serverException handlerMiddlewareRoutingEndpoint selectionRate limiterMiddlewareAuthenticationWho you areAuthorizationWhat you may doModel bindingHTTP → C# + validationControllerEndpoint codeServiceBusiness rules (DI)RedisDistributed cacheEF CoreLINQ → SQLSQL ServerQuery plan, indexes
OUTBOUND →

The contact form is sent, but the e-mail field says ‘ayse-at-ornek’.

BrowserYour screen. It writes the request and finally turns the answer into a page.
1 / 4
01 / PRACTICE

One topic. Three levels of depth.

Illustrative example
// GET /api/posts?page=2&category=Backend
[HttpGet]
public IActionResult List([FromQuery] int page = 1, [FromQuery] string? category = null) => …

Query string values bind to simple parameters.

This page connects to no real server or database. Code samples are illustrative for .NET 8, Next.js and SQL Server; timings are example values in the simulation, not measurements. Try samples only in your own development environment; never share real connection strings, tokens or passwords.

02 / YOUR TURN

Try it yourself first.

The profile update endpoint currently binds the User entity. Users may change only DisplayName and Bio. Make it safe.

Show the solution and explanation
Worked solution
public sealed record UpdateProfile([MaxLength(60)] string DisplayName, [MaxLength(500)] string? Bio);

[HttpPut("me")]
public async Task<IActionResult> Update(UpdateProfile input, CancellationToken ct)
{
    var user = await db.Users.SingleAsync(u => u.Id == CurrentUserId, ct);
    user.DisplayName = input.DisplayName;
    user.Bio = input.Bio;
    await db.SaveChangesAsync(ct);
    return NoContent();
}

Only permitted fields exist in the model and are assigned one by one. The identity comes from the session, not the URL.