
đ Quick Revision Summary
- **Model Binding:** āĻāĻāĻŋ āĻāĻāĻāĻŋ āϏā§āĻŦā§āĻāĻā§āϰāĻŋā§ āĻĒā§āϰāĻā§āϰāĻŋā§āĻž āϝāĻž HTTP Request āĻĨā§āĻā§ āĻĄāĻžāĻāĻž āϏāĻāĻā§āϰāĻš āĻāϰ⧠āϏāϰāĻžāϏāϰāĻŋ Controller-āĻāϰ Action Method Parameter-āĻ āĻŽā§āϝāĻžāĻĒ āĻāϰā§āĨ¤
- **āĻā§āĻĄ āĻ
āĻĒāĻāĻŋāĻŽāĻžāĻāĻā§āĻļāύ:**
Request.Query["key"]āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰ⧠āĻŽā§āϝāĻžāύā§ā§āĻžāϞāĻŋ āĻĄāĻžāĻāĻž āϰāĻŋāĻĄ āĻāϰāĻžāϰ āĻĻā§āϰā§āĻ āĻāĻŦāĻ Error-prone āĻĒāĻĻā§āϧāϤāĻŋ āĻĻā§āϰ āĻāϰ⧠āĻāĻāĻŋ āĻā§āĻĄāĻā§ āĻā§āϞāĻŋāύ āϰāĻžāĻā§āĨ¤ - **Nullable Types:** āĻĄāĻžāĻāĻž āύāĻž āĻĨāĻžāĻāϞ⧠Error āĻā§āĻžāϤ⧠Parameter-āĻāϰ āĻĄā§āĻāĻž āĻāĻžāĻāĻĒā§āϰ āϏāĻžāĻĨā§
?(āϝā§āĻŽāύ:int? bookId) āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāĻž āĻšā§āĨ¤ - **Execution Order:** Model Binding āϏāĻŦāϏāĻŽā§ Action Method āĻāĻā§āϏāĻŋāĻāĻŋāĻāĻ āĻšāĻā§āĻžāϰ āĻ āĻŋāĻ āĻāĻā§ āĻāĻžāĻ āĻāϰā§āĨ¤
- **Priority Rule:** āĻāĻāĻ Parameter-āĻāϰ āĻā§āϝāĻžāϞ⧠āϝāĻĻāĻŋ Route Data (URL path) āĻāĻŦāĻ Query String (
?key=value) āĻāĻā§ āĻāĻžā§āĻāĻžā§ āĻĨāĻžāĻā§, āϤāĻŦā§ Model Binding āϏāĻŦ āϏāĻŽā§ Route Data-āĻā§ āĻŦā§āĻļāĻŋ Priority āĻŦāĻž āĻ āĻā§āϰāĻžāϧāĻŋāĻāĻžāϰ āĻĻā§ā§āĨ¤
đ Comprehensive Breakdown
āĻāĻāĻžāύ⧠āĻā§āϰāĻžāύā§āϏāĻā§āϰāĻŋāĻĒā§āĻā§āϰ āĻĒā§āϰāϤāĻŋāĻāĻŋ āĻŦāĻŋāώ⧠āϧāĻžāĻĒā§ āϧāĻžāĻĒā§, āĻāĻžāϰāĻŖāϏāĻš (Why) āĻāĻŦāĻ āĻā§āĻĄ āĻāĻŽāĻĒā§āϞāĻŋāĻŽā§āύā§āĻā§āĻļāύāϏāĻš āĻŦā§āϝāĻžāĻā§āϝāĻž āĻāϰāĻž āĻšāϞā§:
ā§§. Model Binding-āĻāϰ āĻĒā§āϰā§ā§āĻāύā§ā§āϤāĻž (Priority: 9/10)
āĻā§āύ āĻĒā§āϰā§ā§āĻāύ (The Why):
āϏāĻžāϧāĻžāϰāĻŖāϤ āĻāĻāĻāĻŋ HTTP Get Request āĻĨā§āĻā§ Query String Parameter-āĻāϰ āĻā§āϝāĻžāϞ⧠āĻŦā§āϰ āĻāϰāϤ⧠āĻšāϞ⧠āĻĄā§āĻā§āϞāĻĒāĻžāϰāĻĻā§āϰ Request.Query.ContainsKey("bookId") āĻŦāĻž āĻāϰāĻāĻŽ āĻĻā§āϰā§āĻ āĻā§āĻĄ āϞāĻŋāĻāϤ⧠āĻšā§āĨ¤ āĻāĻāĻŋ āĻŦāĻžāϰāĻŦāĻžāϰ āϞā§āĻāĻž āĻŦāĻŋāϰāĻā§āϤāĻŋāĻāϰ āĻāĻŦāĻ āĻāϤ⧠āĻā§āϞ āĻšāĻā§āĻžāϰ āϏāĻŽā§āĻāĻžāĻŦāύāĻž (Error-prone) āĻĨāĻžāĻā§āĨ¤
Model Binding āĻāĻ āϏāĻŽāϏā§āϝāĻžāϰ āϏāĻŽāĻžāϧāĻžāύ āĻāϰā§āĨ¤ āĻāĻāĻŋ āϏā§āĻŦā§āĻāĻā§āϰāĻŋā§āĻāĻžāĻŦā§ Request āĻĨā§āĻā§ āĻā§āϝāĻžāϞ⧠āύāĻŋā§ā§ Action Method-āĻāϰ Parameter-āĻ āĻŦāϏāĻŋā§ā§ āĻĻā§ā§āĨ¤
Code Implementation:
// â Old/Manual Way (Without Model Binding)
public IActionResult GetBook()
{
if(Request.Query.ContainsKey("bookId"))
{
var id = Request.Query["bookId"];
// do something
}
return View();
}
// â
Smart Way (With Model Binding)
public IActionResult GetBook(int bookId)
{
// ASP.NET Core āϏā§āĻŦā§āĻāĻā§āϰāĻŋā§āĻāĻžāĻŦā§ URL āĻĨā§āĻā§ bookId āĻāϰ āĻā§āϝāĻžāϞ⧠āĻāĻāĻžāύ⧠āĻĒāĻžāϏ āĻāϰāĻŦā§āĨ¤
return Content($"Book ID is: {bookId}");
}
⧍. Missing Values āĻāĻŦāĻ Nullable Parameters (Priority: 8/10)
āĻā§āύ āĻĒā§āϰā§ā§āĻāύ (The Why):
URL-āĻ āϝāĻĻāĻŋ āĻāĻāĻāĻžāϰ āĻā§āύ⧠bookId āύāĻž āĻĻā§ā§, āϤāĻāύ āϏāĻžāϧāĻžāϰāĻŖ int āĻĄā§āĻāĻž āĻāĻžāĻāĻĒ āĻā§āϰā§āϝāĻžāĻļ āĻāϰāϤ⧠āĻĒāĻžāϰ⧠āĻŦāĻž āĻĄāĻŋāĻĢāϞā§āĻ 0 āύāĻŋā§ā§ āύāĻŋāϤ⧠āĻĒāĻžāϰā§, āϝāĻž āϞāĻāĻŋāĻā§āϝāĻžāϞ āĻŦāĻžāĻ āϤā§āϰāĻŋ āĻāϰā§āĨ¤ āϤāĻžāĻ Optional āĻĒā§āϝāĻžāϰāĻžāĻŽāĻŋāĻāĻžāϰā§āϰ āĻā§āώā§āϤā§āϰ⧠Nullable Type (?) āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāϤ⧠āĻšā§āĨ¤
Code Implementation:
public IActionResult GetBook(int? bookId)
{
// āĻā§āϝāĻžāϞ⧠āĻĻā§āĻā§āĻž āĻšā§ā§āĻā§ āĻāĻŋāύāĻž āϤāĻž āĻā§āĻ āĻāϰāĻž
if (!bookId.HasValue)
{
return BadRequest("Book ID is not supplied or empty.");
}
if (bookId < 0)
{
return BadRequest("Book ID cannot be less than zero.");
}
return Content($"Book ID is: {bookId}");
}
ā§Š. Route Data āĻāĻŦāĻ Query String (Priority: 7/10)
- Route Data: āĻāĻāĻŋ URL-āĻāϰ āĻŽā§āϞ Path-āĻāϰ āĻ
āĻāĻļāĨ¤ āϰāĻžāĻāĻāĻŋāĻ āĻāύāĻĢāĻŋāĻāĻžāϰā§āĻļāύā§
{}(Curly braces) āĻĻāĻŋā§ā§ āĻāĻā§āϞ⧠āĻĄāĻŋāĻĢāĻžāĻāύ āĻāϰāĻž āĻšā§āĨ¤ āϝā§āĻŽāύ:/bookstore/{bookId}āĨ¤ - Query String: āĻāĻāĻŋ URL-āĻāϰ āĻļā§āώā§
?āĻāĻŋāĻšā§āύā§āϰ āĻĒāϰ āĻĨāĻžāĻā§ āĻāĻŦāĻ Key-Value āĻĒā§ā§āĻžāϰ āĻšāĻŋāϏā§āĻŦā§ āĻāĻžāĻ āĻāϰā§āĨ¤ āϝā§āĻŽāύ:/bookstore?bookId=10āĨ¤
ā§Ē. Model Binding Priority Rule: Route Data vs Query String (Priority: 10/10)
āĻā§āύ āĻĒā§āϰā§ā§āĻāύ (The Why): āĻāĻāύ⧠āĻāĻāύ⧠āĻāĻāĻāĻžāϰ āĻāĻāĻ āύāĻžāĻŽā§āϰ Parameter, Route Data āĻāĻŦāĻ Query String āĻāĻā§ āĻāĻžā§āĻāĻžā§ āĻĒāĻžāĻ āĻŋā§ā§ āĻĻāĻŋāϤ⧠āĻĒāĻžāϰā§āĨ¤ āĻāĻ āĻāύāĻĢā§āϞāĻŋāĻā§āĻ āĻŦāĻž āĻĻā§āĻŦāύā§āĻĻā§āĻŦ āĻŽā§āĻāĻžāύā§āϰ āĻāύā§āϝ ASP.NET Core-āĻ āĻāĻāĻāĻŋ āύāĻŋāϰā§āĻĻāĻŋāώā§āĻ Order āĻŦāĻž āĻā§āϰāĻŽāĻžāύā§āϏāĻžāϰ⧠āĻĄāĻžāĻāĻž āϰāĻŋāĻĄ āĻāϰāĻž āĻšā§āĨ¤
āĻā§āϰāĻžāύā§āϏāĻā§āϰāĻŋāĻĒā§āĻā§ āĻŦāϞāĻž āĻšā§ā§āĻā§, Model Binding Top to Bottom āĻ ā§āϝāĻžāĻĒā§āϰā§āĻā§ āĻāĻžāĻ āĻāϰ⧠āĻāĻŦāĻ Route Data-āĻāϰ Priority, Query String-āĻāϰ āĻā§ā§ā§ āĻŦā§āĻļāĻŋāĨ¤
Scenario / Code Implementation: āϧāϰāĻž āϝāĻžāĻ āĻāĻŽāĻžāĻĻā§āϰ Route āĻāύāĻĢāĻŋāĻāĻžāϰā§āĻļāύ āύāĻŋāĻā§āϰ āĻŽāϤā§:
[Route("bookstore/{bookId?}/{isLoggedIn?}")]
public IActionResult GetBookInfo(int? bookId, bool? isLoggedIn)
{
return Content($"Book: {bookId}, Logged In: {isLoggedIn}");
}
āĻāĻāύ āϝāĻĻāĻŋ āĻāĻāĻāĻžāϰ āύāĻŋāĻā§āϰ URL-āĻ Request āĻĒāĻžāĻ āĻžā§:
http://localhost:5202/bookstore/1/false?bookId=10&isLoggedIn=true
āĻāĻāĻžāύā§:
- Route Data:
bookId=1,isLoggedIn=false - Query String:
bookId=10,isLoggedIn=true
āĻĢāϞāĻžāĻĢāϞ: āϝā§āĻšā§āϤ⧠Route Data-āĻāϰ āĻĒā§āϰāĻžā§ā§āϰāĻŋāĻāĻŋ āĻŦā§āĻļāĻŋ, āϤāĻžāĻ Action Method-āĻāϰ Parameter āĻšāĻŋāϏā§āĻŦā§ 1 āĻāĻŦāĻ false āϰāĻŋāϏāĻŋāĻ āĻšāĻŦā§āĨ¤ Query String-āĻāϰ 10 āĻāĻŦāĻ true āĻāĻāύā§āϰ āĻāϰāĻž āĻšāĻŦā§āĨ¤
(āύā§āĻ: āύāĻŋāϰā§āĻĻāĻŋāώā§āĻ āĻā§āύ⧠āϏā§āϰā§āϏ āĻĨā§āĻā§ āĻĄāĻžāĻāĻž āύāĻŋāϤ⧠āĻāĻžāĻāϞ⧠[FromQuery] āĻŦāĻž [FromRoute] āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāϤ⧠āĻšā§, āϝāĻž āĻā§āϰāĻžāύā§āϏāĻā§āϰāĻŋāĻĒā§āĻā§ āĻĒāϰāĻŦāϰā§āϤ⧠āϞā§āĻāĻāĻžāϰā§āϰ āĻāĻĒāĻŋāĻ āĻšāĻŋāϏā§āĻŦā§ āĻāϞā§āϞā§āĻ āĻāϰāĻž āĻšā§ā§āĻā§āĨ¤)
đĄ Best Practices
- Always use Nullable Types for Optional Data: āϝāĻĻāĻŋ āĻā§āύ⧠Parameter āĻāĻŦāĻļā§āϝāĻŋāĻ (Required) āύāĻž āĻšā§, āϤāĻŦā§ āϏāĻŦāϏāĻŽā§
int?,bool?āĻāϤā§āϝāĻžāĻĻāĻŋ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰā§āύāĨ¤ āĻāϤ⧠Null Reference Exception āĻā§āĻžāύ⧠āϝāĻžā§āĨ¤ - Explicit Attributes āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāĻž: āĻā§āĻĄā§āϰ āϰāĻŋāĻĄā§āĻŦāĻŋāϞāĻŋāĻāĻŋ āĻŦāĻžā§āĻžāύā§āϰ āĻāύā§āϝ āĻĄāĻžāĻāĻž āĻā§āĻĨāĻž āĻĨā§āĻā§ āĻāϏāĻŦā§ āϤāĻž āϏā§āĻĒāώā§āĻāĻāĻžāĻŦā§ āĻŦāϞ⧠āĻĻā§āĻā§āĻž āĻāĻāĻŋāϤāĨ¤
// Example
public IActionResult ProcessData([FromRoute] int id, [FromQuery] string search)
{ ... }
- Naming Convention: Route Parameter āĻāĻŦāĻ Action Method Parameter-āĻāϰ āύāĻžāĻŽ āĻšā§āĻŦāĻšā§ āĻāĻ āϰāĻžāĻāĻž āĻāĻāĻŋāϤ (āϝāĻĻāĻŋāĻ āĻāĻāĻŋ Case-Insensitive, āϤāĻŦā§āĻ āĻā§āϞāĻŋāύ āĻā§āĻĄā§āϰ āĻāύā§āϝ āĻāĻāĻ Case āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāĻž āĻāĻžāϞā§)āĨ¤
đ .NET 10 Update (Changes from .NET 6)
āĻā§āϰāĻžāύā§āϏāĻā§āϰāĻŋāĻĒā§āĻā§āϰ āĻāύāϏā§āĻĒā§āĻāĻā§āϞ⧠.NET 6 āĻŦāĻž āϤāĻžāϰ āĻāĻā§āϰ āĻāĻžāϰā§āϏāύā§āϰ āĻāύā§āĻā§āϰā§āϞāĻžāϰ-āĻāĻŋāϤā§āϤāĻŋāĻ āĻāϰā§āĻāĻŋāĻā§āĻāĻāĻžāϰā§āϰ āĻāĻĒāϰ āĻāĻŋāϤā§āϤāĻŋ āĻāϰā§āĨ¤ .NET 10-āĻ (āĻāĻŦāĻ .NET 8/9 āĻāϰ āϧāĻžāϰāĻžāĻŦāĻžāĻšāĻŋāĻāϤāĻžā§) Minimal APIs-āĻ Model Binding-āĻā§ āĻāϰāĻ āĻ āύā§āĻ āĻŦā§āĻļāĻŋ āĻļāĻā§āϤāĻŋāĻļāĻžāϞ⧠āĻāĻŦāĻ Implicit āĻāϰāĻž āĻšā§ā§āĻā§āĨ¤
.NET 10-āĻ [AsParameters] āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰ⧠āĻ
āύā§āĻāĻā§āϞ⧠Query āĻŦāĻž Route parameter-āĻā§ āĻā§āĻŦ āϏāĻšāĻā§āĻ āĻāĻāĻāĻŋ āĻ
āĻŦāĻā§āĻā§āĻā§ āĻŦāĻžāĻāύā§āĻĄ āĻāϰāĻž āϝāĻžā§, āϝāĻž āĻāύā§āĻā§āϰā§āϞāĻžāϰā§āϰ āĻĒā§āϝāĻžāϰāĻžāĻŽāĻŋāĻāĻžāϰ āϞāĻŋāϏā§āĻāĻā§ āĻā§āĻ āĻ āϏā§āύā§āĻĻāϰ āϰāĻžāĻā§āĨ¤
.NET 10 Code Implementation Example:
// āĻāĻāĻāĻŋ āϰā§āĻāϰā§āĻĄ āĻāĻžāĻāĻĒ āϤā§āϰāĻŋ āĻāϰāĻž āĻšāϞā§
public record BookRequest(int? BookId, bool? IsLoggedIn);
var app = WebApplication.CreateBuilder(args).Build();
// Minimal API with [AsParameters]
app.MapGet("/bookstore/{BookId?}/{IsLoggedIn?}", ([AsParameters] BookRequest request) =>
{
if (request.BookId is null) return Results.BadRequest("ID missing");
// Route Data āĻāĻŦāĻ Query String āĻĨā§āĻā§ āϏā§āĻŦā§āĻāĻā§āϰāĻŋā§āĻāĻžāĻŦā§ BookRequest āĻ
āĻŦāĻā§āĻā§āĻā§ āĻĄāĻžāĻāĻž āĻŽā§āϝāĻžāĻĒ āĻšā§ā§ āϝāĻžāĻŦā§
return Results.Ok($"Book: {request.BookId}, LoggedIn: {request.IsLoggedIn}");
});
app.Run();
.NET 10-āĻ Reflection-āĻāϰ āĻŦāĻĻāϞ⧠Source Generators āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāĻžā§ āĻāĻ Model Binding āĻāĻāύ āĻ āύā§āĻ āĻŦā§āĻļāĻŋ āĻĢāĻžāϏā§āĻ āĻāĻŦāĻ āĻŽā§āĻŽāϰāĻŋ āĻāĻĢāĻŋāĻļāĻŋā§ā§āύā§āĻāĨ¤