Model binding no ASP.NET CoreModel Binding in ASP.NET Core

Por Rachel AppelBy Rachel Appel

Introdução ao model bindingIntroduction to model binding

O model binding do ASP.NET Core MVC mapeia dados de solicitações HTTP para parâmetros de método de ação.Model binding in ASP.NET Core MVC maps data from HTTP requests to action method parameters. Os parâmetros podem ser tipos simples, como cadeias de caracteres, inteiros ou floats, ou podem ser tipos complexos.The parameters may be simple types such as strings, integers, or floats, or they may be complex types. Esse é um ótimo recurso do MVC, pois o mapeamento dos dados de entrada para um equivalente é um cenário repetido com frequência, independentemente do tamanho ou da complexidade dos dados.This is a great feature of MVC because mapping incoming data to a counterpart is an often repeated scenario, regardless of size or complexity of the data. O MVC resolve esse problema com a abstração da associação, de modo que os desenvolvedores não precisem continuar reconfigurando uma versão ligeiramente diferente desse mesmo código em cada aplicativo.MVC solves this problem by abstracting binding away so developers don't have to keep rewriting a slightly different version of that same code in every app. A escrita de seu próprio texto para tipar o código de conversor é entediante e propensa a erros.Writing your own text to type converter code is tedious, and error prone.

Como funciona o model bindingHow model binding works

Quando o MVC recebe uma solicitação HTTP, ele encaminha-a a um método de ação específico de um controlador.When MVC receives an HTTP request, it routes it to a specific action method of a controller. Ele determina qual método de ação será executado com base no que está nos dados de rota e, em seguida, ele associa valores da solicitação HTTP aos parâmetros desse método de ação.It determines which action method to run based on what is in the route data, then it binds values from the HTTP request to that action method's parameters. Por exemplo, considere a seguinte URL:For example, consider the following URL:

http://contoso.com/movies/edit/2

Como o modelo de rota é semelhante a isto, {controller=Home}/{action=Index}/{id?}, movies/edit/2 encaminha para o controlador Movies e seu método de ação Edit.Since the route template looks like this, {controller=Home}/{action=Index}/{id?}, movies/edit/2 routes to the Movies controller, and its Edit action method. Ele também aceita um parâmetro opcional chamado id.It also accepts an optional parameter called id. O código para o método de ação deve ter esta aparência:The code for the action method should look something like this:

public IActionResult Edit(int? id)

Observação: as cadeias de caracteres na rota de URL não diferenciam maiúsculas de minúsculas.Note: The strings in the URL route are not case sensitive.

O MVC tentará associar os dados de solicitação aos parâmetros de ação por nome.MVC will try to bind request data to the action parameters by name. O MVC procurará valores para cada parâmetro usando o nome do parâmetro e os nomes de suas propriedades configuráveis públicas.MVC will look for values for each parameter using the parameter name and the names of its public settable properties. No exemplo acima, o único parâmetro de ação é chamado id, que o MVC associa ao valor com o mesmo nome nos valores de rota.In the above example, the only action parameter is named id, which MVC binds to the value with the same name in the route values. Além dos valores de rota, o MVC associará dados de várias partes da solicitação e faz isso em uma ordem específica.In addition to route values MVC will bind data from various parts of the request and it does so in a set order. Veja abaixo uma lista das fontes de dados na ordem em que o model binding examina-as:Below is a list of the data sources in the order that model binding looks through them:

  1. Form values: esses são valores de formulário que entram na solicitação HTTP usando o método POST.Form values: These are form values that go in the HTTP request using the POST method. (incluindo as solicitações POST jQuery).(including jQuery POST requests).

  2. Route values: o conjunto de valores de rota fornecido pelo RoteamentoRoute values: The set of route values provided by Routing

  3. Query strings: a parte da cadeia de caracteres de consulta do URI.Query strings: The query string part of the URI.

Observação: valores de formulário, dados de rota e cadeias de consulta são todos armazenados como pares nome-valor.Note: Form values, route data, and query strings are all stored as name-value pairs.

Como o model binding solicitou uma chave chamada id e não há nada chamado id nos valores de formulário, ela passou para os valores de rota procurando essa chave.Since model binding asked for a key named id and there's nothing named id in the form values, it moved on to the route values looking for that key. Em nosso exemplo, isso é uma correspondência.In our example, it's a match. A associação ocorre e o valor é convertido no inteiro 2.Binding happens, and the value is converted to the integer 2. A mesma solicitação que usa Edit(string id) converterá na cadeia de caracteres "2".The same request using Edit(string id) would convert to the string "2".

Até agora, o exemplo usa tipos simples.So far the example uses simple types. No MVC, os tipos simples são qualquer tipo primitivo do .NET ou um tipo com um conversor de tipo de cadeia de caracteres.In MVC simple types are any .NET primitive type or type with a string type converter. Se o parâmetro do método de ação for uma classe, como o tipo Movie, que contém tipos simples e complexos como propriedades, o model binding do MVC ainda o manipulará perfeitamente.If the action method's parameter were a class such as the Movie type, which contains both simple and complex types as properties, MVC's model binding will still handle it nicely. Ele usa a reflexão e recursão para percorrer as propriedades de tipos complexos procurando correspondências.It uses reflection and recursion to traverse the properties of complex types looking for matches. O model binding procura o padrão nome_do_parâmetro.nome_da_propriedade para associar valores a propriedades.Model binding looks for the pattern parameter_name.property_name to bind values to properties. Se ela não encontrar os valores correspondentes desse formulário, ela tentará associar usando apenas o nome da propriedade.If it doesn't find matching values of this form, it will attempt to bind using just the property name. Para esses tipos como tipos Collection, o model binding procura correspondências para parameter_name [index] ou apenas [index].For those types such as Collection types, model binding looks for matches to parameter_name[index] or just [index]. O model binding trata tipos Dictionary da mesma forma, solicitando parameter_name[key] ou apenas [key], desde que as chaves sejam tipos simples.Model binding treats Dictionary types similarly, asking for parameter_name[key] or just [key], as long as the keys are simple types. As chaves compatíveis correspondem o HTML dos nomes de campo e os auxiliares de marca gerados para o mesmo tipo de modelo.Keys that are supported match the field names HTML and tag helpers generated for the same model type. Isso permite a ida e vinda dos valores, de modo que os campos de formulário permaneçam preenchidos com a entrada do usuário para sua conveniência, por exemplo, quando os dados associados de uma criação ou edição não são aprovados na validação.This enables round-tripping values so that the form fields remain filled with the user's input for their convenience, for example, when bound data from a create or edit didn't pass validation.

Para possibilitar o model binding, a classe deve ter um construtor padrão público e propriedades públicas graváveis para associar.To make model binding possible, the class must have a public default constructor and public writable properties to bind. Quando o model binding ocorrer, será criada uma instância da classe usando o construtor padrão público e, em seguida, as propriedades poderão ser definidas.When model binding occurs, the class is instantiated using the public default constructor, then the properties can be set.

Quando um parâmetro é associado, o model binding para de procurar valores com esse nome e ele passa para associar o próximo parâmetro.When a parameter is bound, model binding stops looking for values with that name and it moves on to bind the next parameter. Caso contrário, o comportamento padrão do model binding define parâmetros com seus valores padrão, dependendo de seu tipo:Otherwise, the default model binding behavior sets parameters to their default values depending on their type:

  • T[]: com a exceção de matrizes do tipo byte[], a associação define parâmetros do tipo T[] como Array.Empty<T>().T[]: With the exception of arrays of type byte[], binding sets parameters of type T[] to Array.Empty<T>(). Matrizes do tipo byte[] são definidas como null.Arrays of type byte[] are set to null.

  • Tipos de referência: a associação cria uma instância de uma classe com o construtor padrão sem configurar propriedades.Reference Types: Binding creates an instance of a class with the default constructor without setting properties. No entanto, o model binding define parâmetros string como null.However, model binding sets string parameters to null.

  • Tipos que permitem valor nulo: os tipos que permitem valor nulo são definidos como null.Nullable Types: Nullable types are set to null. No exemplo acima, o model binding define id como null, pois ele é do tipo int?.In the above example, model binding sets id to null since it's of type int?.

  • Tipos de valor: os tipos de valor que não permitem valor nulo do tipo T são definidos como default(T).Value Types: Non-nullable value types of type T are set to default(T). Por exemplo, o model binding definirá um parâmetro int id como 0.For example, model binding will set a parameter int id to 0. Considere o uso da validação de modelo ou de tipos que permitem valor nulo, em vez de depender de valores padrão.Consider using model validation or nullable types rather than relying on default values.

Se a associação falhar, o MVC não gerará um erro.If binding fails, MVC doesn't throw an error. Todas as ações que aceitam a entrada do usuário devem verificar a propriedade ModelState.IsValid.Every action which accepts user input should check the ModelState.IsValid property.

Observação: cada entrada na propriedade ModelState do controlador é uma ModelStateEntry que contém uma propriedade Errors.Note: Each entry in the controller's ModelState property is a ModelStateEntry containing an Errors property. Raramente é necessário consultar essa coleção por conta própria.It's rarely necessary to query this collection yourself. Use ModelState.IsValid em seu lugar.Use ModelState.IsValid instead.

Além disso, há alguns tipos de dados especiais que o MVC precisa considerar ao realizar o model binding:Additionally, there are some special data types that MVC must consider when performing model binding:

  • IFormFile, IEnumerable<IFormFile>: um ou mais arquivos carregados que fazem parte da solicitação HTTP.IFormFile, IEnumerable<IFormFile>: One or more uploaded files that are part of the HTTP request.

  • CancellationToken: usado para cancelar a atividade em controladores assíncronos.CancellationToken: Used to cancel activity in asynchronous controllers.

Esses tipos podem ser associados a parâmetros de ação ou a propriedades em um tipo de classe.These types can be bound to action parameters or to properties on a class type.

Após a conclusão do model binding, a Validação ocorrerá.Once model binding is complete, Validation occurs. O model binding padrão funciona bem para a maioria dos cenários de desenvolvimento.Default model binding works great for the vast majority of development scenarios. Também é extensível e, portanto, se você tiver necessidades exclusivas, poderá personalizar o comportamento interno.It's also extensible so if you have unique needs you can customize the built-in behavior.

Personalizar o comportamento do model binding com atributosCustomize model binding behavior with attributes

O MVC contém vários atributos que podem ser usados para direcionar seu comportamento de model binding padrão para outra fonte.MVC contains several attributes that you can use to direct its default model binding behavior to a different source. Por exemplo, você pode especificar se a associação é obrigatória para uma propriedade ou se ela nunca deve ocorrer usando os atributos [BindRequired] ou [BindNever].For example, you can specify whether binding is required for a property, or if it should never happen at all by using the [BindRequired] or [BindNever] attributes. Como alternativa, você pode substituir a fonte de dados padrão e especificar a fonte de dados do associador de modelos.Alternatively, you can override the default data source, and specify the model binder's data source. Veja abaixo uma lista dos atributos de model binding:Below is a list of model binding attributes:

  • [BindRequired]: esse atributo adiciona um erro de estado do modelo se a associação não pode ocorrer.[BindRequired]: This attribute adds a model state error if binding cannot occur.

  • [BindNever]: instrui o associador de modelos a nunca associar a esse parâmetro.[BindNever]: Tells the model binder to never bind to this parameter.

  • [FromHeader], [FromQuery], [FromRoute], [FromForm]: use-os para especificar a origem da associação exata que deseja aplicar.[FromHeader], [FromQuery], [FromRoute], [FromForm]: Use these to specify the exact binding source you want to apply.

  • [FromServices]: esse atributo usa a injeção de dependência para associar parâmetros de serviços.[FromServices]: This attribute uses dependency injection to bind parameters from services.

  • [FromBody]: use os formatadores configurados para associar dados do corpo da solicitação.[FromBody]: Use the configured formatters to bind data from the request body. O formatador é selecionado de acordo com o tipo de conteúdo da solicitação.The formatter is selected based on content type of the request.

  • [ModelBinder]: usado para substituir o associador de modelos padrão, a origem da associação e o nome.[ModelBinder]: Used to override the default model binder, binding source and name.

Os atributos são ferramentas muito úteis quando você precisa substituir o comportamento padrão do model binding.Attributes are very helpful tools when you need to override the default behavior of model binding.

Personalizar a validação e o model binding globalmenteCustomize model binding and validation globally

O comportamento do sistema de validação e model binding é orientado pelo ModelMetadata que descreve:The model binding and validation system's behavior is driven by ModelMetadata that describes:

  • Como um modelo deve ser associado.How a model is to be bound.
  • Como ocorre a validação no tipo e em suas propriedades.How validation occurs on the type and its properties.

Os aspectos do comportamento do sistema podem ser configurados globalmente adicionando um provedor de detalhes a MvcOptions.ModelMetadataDetailsProviders.Aspects of the system's behavior can be configured globally by adding a details provider to MvcOptions.ModelMetadataDetailsProviders. O MVC tem alguns provedores de detalhes internos que permitem configurar o comportamento, como desabilitar a validação ou o model binding de determinados tipos.MVC has a few built-in details providers that allow configuring behavior such as disabling model binding or validation for certain types.

Para desabilitar o model binding em todos os modelos de um determinado tipo, adicione um ExcludeBindingMetadataProvider em Startup.ConfigureServices.To disable model binding on all models of a certain type, add an ExcludeBindingMetadataProvider in Startup.ConfigureServices. Por exemplo, para desabilitar o model binding em todos os modelos do tipo System.Version:For example, to disable model binding on all models of type System.Version:

services.AddMvc().AddMvcOptions(options =>
    options.ModelMetadataDetailsProviders.Add(
        new ExcludeBindingMetadataProvider(typeof(System.Version))));

Para desabilitar a validação nas propriedades de um determinado tipo, adicione um SuppressChildValidationMetadataProvider em Startup.ConfigureServices.To disable validation on properties of a certain type, add a SuppressChildValidationMetadataProvider in Startup.ConfigureServices. Por exemplo, para desabilitar a validação nas propriedades do tipo System.Guid:For example, to disable validation on properties of type System.Guid:

services.AddMvc().AddMvcOptions(options =>
    options.ModelMetadataDetailsProviders.Add(
        new SuppressChildValidationMetadataProvider(typeof(System.Guid))));

Associar dados formatados do corpo da solicitaçãoBind formatted data from the request body

Os dados de solicitação podem ser recebidos em uma variedade de formatos, incluindo JSON, XML e muitos outros.Request data can come in a variety of formats including JSON, XML and many others. Quando você usa o atributo [FromBody] para indicar que deseja associar um parâmetro a dados no corpo da solicitação, o MVC usa um conjunto configurado de formatadores para manipular os dados de solicitação de acordo com seu tipo de conteúdo.When you use the [FromBody] attribute to indicate that you want to bind a parameter to data in the request body, MVC uses a configured set of formatters to handle the request data based on its content type. Por padrão, o MVC inclui uma classe JsonInputFormatter para manipular dados JSON, mas você pode adicionar outros formatadores para manipular XML e outros formatos personalizados.By default MVC includes a JsonInputFormatter class for handling JSON data, but you can add additional formatters for handling XML and other custom formats.

Observação

Pode haver, no máximo, um parâmetro por ação decorado com [FromBody].There can be at most one parameter per action decorated with [FromBody]. O tempo de execução do ASP.NET Core MVC delega a responsabilidade de ler o fluxo da solicitação ao formatador.The ASP.NET Core MVC run-time delegates the responsibility of reading the request stream to the formatter. Depois que o fluxo da solicitação é lido para um parâmetro, geralmente, não é possível ler o fluxo da solicitação novamente para associar outros parâmetros [FromBody].Once the request stream is read for a parameter, it's generally not possible to read the request stream again for binding other [FromBody] parameters.

Observação

O JsonInputFormatter é o formatador padrão e se baseia no Json.NET.The JsonInputFormatter is the default formatter and is based on Json.NET.

O ASP.NET Core seleciona formatadores de entrada com base no cabeçalho Content-Type e no tipo do parâmetro, a menos que haja um atributo aplicado a ele com outra especificação.ASP.NET Core selects input formatters based on the Content-Type header and the type of the parameter, unless there's an attribute applied to it specifying otherwise. Se deseja usar XML ou outro formato, configure-o no arquivo Startup.cs, mas talvez você precise obter primeiro uma referência a Microsoft.AspNetCore.Mvc.Formatters.Xml usando o NuGet.If you'd like to use XML or another format you must configure it in the Startup.cs file, but you may first have to obtain a reference to Microsoft.AspNetCore.Mvc.Formatters.Xml using NuGet. O código de inicialização deverá ter uma aparência semelhante a esta:Your startup code should look something like this:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc()
        .AddXmlSerializerFormatters();
   }

O código no arquivo Startup.cs contém um método ConfigureServices com um argumento services que você pode usar para criar serviços para o aplicativo ASP.NET Core.Code in the Startup.cs file contains a ConfigureServices method with a services argument you can use to build up services for your ASP.NET Core app. No exemplo, estamos adicionando um formatador XML como um serviço que o MVC fornecerá para este aplicativo.In the sample, we are adding an XML formatter as a service that MVC will provide for this app. O argumento options passado para o método AddMvc permite que você adicione e gerencie filtros, formatadores e outras opções do sistema no MVC após a inicialização do aplicativo.The options argument passed into the AddMvc method allows you to add and manage filters, formatters, and other system options from MVC upon app startup. Em seguida, aplique o atributo Consumes a classes do controlador ou métodos de ação para trabalhar com o formato desejado.Then apply the Consumes attribute to controller classes or action methods to work with the format you want.

Model binding personalizadoCustom Model Binding

Estenda o model binding escrevendo seus próprios associadores de modelos personalizados.You can extend model binding by writing your own custom model binders. Saiba mais sobre o model binding personalizado.Learn more about custom model binding.