1. Model Binding — de texto para objeto tipado
Toda requisição HTTP chega como texto (query string, corpo do formulário, corpo JSON). Model binding é o processo automático do ASP.NET Core que lê esse texto e monta um objeto C# — convertendo tipos, casando nomes de campo com propriedades, tudo antes do seu código de Action rodar:
[HttpPost]
public async Task<IActionResult> Novo(ClienteCadastroViewModel modelo)
{
// "modelo" já chega aqui totalmente preenchido —
// o framework já leu o corpo do POST e converteu cada campo
...
}
Fig. 1 — Model binding transforma texto de requisição em objeto tipado antes da Action executar.
2. Fontes de binding: [FromForm], [FromQuery], [FromBody], [FromRoute]
Por padrão, o model binding procura o valor em várias fontes automaticamente. Atributos deixam a origem explícita quando necessário:
[HttpGet("clientes/buscar")]
public IActionResult Buscar([FromQuery] string nome) // ?nome=ana
{
...
}
[HttpGet("clientes/{id:int}")]
public IActionResult Detalhes([FromRoute] int id) // /clientes/42
{
...
}
[HttpPost("clientes")]
public IActionResult Criar([FromBody] ClienteCadastroViewModel modelo) // JSON no corpo
{
...
}
3. Data Annotations — validação declarativa
Você já viu isso brevemente no capítulo anterior. Data Annotations são atributos que descrevem
regras de validação direto na classe, sem precisar de ifs espalhados
pelo Controller:
public class ClienteCadastroViewModel
{
[Required(ErrorMessage = "O nome é obrigatório")]
[StringLength(100, MinimumLength = 2)]
public string Nome { get; set; } = string.Empty;
[Required]
[EmailAddress(ErrorMessage = "E-mail inválido")]
public string Email { get; set; } = string.Empty;
[Range(18, 120, ErrorMessage = "Idade deve estar entre 18 e 120")]
public int Idade { get; set; }
[RegularExpression(@"^\d{5}-\d{3}$", ErrorMessage = "CEP inválido")]
public string Cep { get; set; } = string.Empty;
}
4. Checando a validação no Controller
[HttpPost]
public async Task<IActionResult> Novo(ClienteCadastroViewModel modelo)
{
if (!ModelState.IsValid)
return View(modelo); // devolve a mesma tela, com os erros visíveis via Tag Helpers
await _service.CriarAsync(ClienteMapper.ParaEntidade(modelo));
return RedirectToAction(nameof(Listar));
}
ModelState é preenchido automaticamente pelo framework durante o model
binding — cada Data Annotation violada vira uma entrada nele. Do lado da View, o Tag Helper
asp-validation-for (visto no capítulo 3) exibe a mensagem
correspondente ao lado de cada campo.
5. Validação customizada
Quando uma regra não se encaixa num atributo pronto, implemente IValidatableObject:
public class PedidoCadastroViewModel : IValidatableObject
{
public DateTime DataEntregaDesejada { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext contexto)
{
if (DataEntregaDesejada < DateTime.Today)
{
yield return new ValidationResult(
"A data de entrega não pode ser no passado",
new[] { nameof(DataEntregaDesejada) });
}
}
}
Data Annotations validam a forma dos dados antes de chegar à regra de negócio —
mas nunca confie só nelas. As checagens de integridade que você já implementou nas procedures do
Módulo 2 (como THROW quando estoque é insuficiente) continuam sendo a
última linha de defesa, porque a Action pode ser chamada de outras formas além de um formulário
HTML validado (uma chamada de API direta, por exemplo).
6. Onde isso te leva
Com model binding e validação cobertos, os dois últimos capítulos deste módulo tratam de como o ASP.NET Core monta as dependências que os Controllers recebem (Injeção de Dependência) e o que acontece com uma requisição antes/depois de chegar numa Action (Filters e Middlewares).