ASP.NET Core 中的模型绑定Model Binding in ASP.NET Core

本文解释了模型绑定的定义、模型绑定的工作原理,以及如何自定义模型绑定的行为。This article explains what model binding is, how it works, and how to customize its behavior.

查看或下载示例代码如何下载)。View or download sample code (how to download).

什么是模型绑定What is Model binding

控制器和 Razor Pages 处理来自 HTTP 请求的数据。Controllers and Razor pages work with data that comes from HTTP requests. 例如,路由数据可以提供一个记录键,而发布的表单域可以为模型的属性提供一个值。For example, route data may provide a record key, and posted form fields may provide values for the properties of the model. 编写代码以检索这些值,并将其从字符串转换为 .NET 类型不仅繁琐,而且还容易出错。Writing code to retrieve each of these values and convert them from strings to .NET types would be tedious and error-prone. 模型绑定会自动化该过程。Model binding automates this process. 模型绑定系统:The model binding system:

  • 从各种源(如路由数据、表单域和查询字符串)中检索数据。Retrieves data from various sources such as route data, form fields, and query strings.
  • 将数据提供给方法参数和公共属性中的控制器和 Razor Pages。Provides the data to controllers and Razor pages in method parameters and public properties.
  • 将字符串数据转换为 .NET 类型。Converts string data to .NET types.
  • 更新复杂类型的属性。Updates properties of complex types.

示例Example

假设有以下操作方法:Suppose you have the following action method:

[HttpGet("{id}")]
public ActionResult<Pet> GetById(int id, bool dogsOnly)

并且应用收到一个带有以下 URL 的请求:And the app receives a request with this URL:

http://contoso.com/api/pets/2?DogsOnly=true

在路由系统选择该操作方法之后,模型绑定执行以下步骤:Model binding goes through the following steps after the routing system selects the action method:

  • 查找 GetByID 的第一个参数,该参数是一个名为 id 的整数。Finds the first parameter of GetByID, an integer named id.
  • 查找 HTTP 请求中的可用源,并在路由数据中查找 id =“2”。Looks through the available sources in the HTTP request and finds id = "2" in route data.
  • 将字符串“2”转换为整数 2。Converts the string "2" into integer 2.
  • 查找 GetByID 的下一个参数,该参数是一个名为 dogsOnly 的布尔值。Finds the next parameter of GetByID, a boolean named dogsOnly.
  • 查找源,并在查询字符串中查找“DogsOnly=true”。Looks through the sources and finds "DogsOnly=true" in the query string. 名称匹配不区分大小写。Name matching is not case-sensitive.
  • 将字符串“true”转换为布尔值 trueConverts the string "true" into boolean true.

然后,该框架会调用 GetById 方法,为 id 参数传入 2,并为 dogsOnly 参数传入 trueThe framework then calls the GetById method, passing in 2 for the id parameter, and true for the dogsOnly parameter.

在前面的示例中,模型绑定目标是简单类型的方法参数。In the preceding example, the model binding targets are method parameters that are simple types. 目标也可以是复杂类型的属性。Targets may also be the properties of a complex type. 成功绑定每个属性后,将对属性进行模型验证After each property is successfully bound, model validation occurs for that property. 有关绑定到模型的数据以及任意绑定或验证错误的记录都存储在 ControllerBase.ModelStatePageModel.ModelState 中。The record of what data is bound to the model, and any binding or validation errors, is stored in ControllerBase.ModelState or PageModel.ModelState. 为查明该过程是否已成功,应用会检查 ModelState.IsValid 标志。To find out if this process was successful, the app checks the ModelState.IsValid flag.

目标Targets

模型绑定尝试查找以下类型目标的值:Model binding tries to find values for the following kinds of targets:

  • 将请求路由到的控制器操作方法的参数。Parameters of the controller action method that a request is routed to.
  • 将请求路由到的 Razor Pages 处理程序方法的参数。Parameters of the Razor Pages handler method that a request is routed to.
  • 控制器或 PageModel 类的公共属性(若由特性指定)。Public properties of a controller or PageModel class, if specified by attributes.

[BindProperty] 属性[BindProperty] attribute

可应用于控制器或 PageModel 类的公共属性,从而使模型绑定以该属性为目标:Can be applied to a public property of a controller or PageModel class to cause model binding to target that property:

public class EditModel : InstructorsPageModel
{
    public EditModel() : base()
    {
    }

    [BindProperty]
    public Instructor Instructor { get; set; }

[BindProperties] 属性[BindProperties] attribute

可在 ASP.NET Core 2.1 及更高版本中获得。Available in ASP.NET Core 2.1 and later. 可应用于控制器或 PageModel 类,以使模型绑定以该类的所有公共属性为目标:Can be applied to a controller or PageModel class to tell model binding to target all public properties of the class:

[BindProperties(SupportsGet=true)]
public class CreateModel : InstructorsPageModel
{
    public CreateModel() : base()
    {
    }

    public Instructor Instructor { get; set; }

HTTP GET 请求的模型绑定Model binding for HTTP GET requests

默认情况下,不绑定 HTTP GET 请求的属性。By default, properties are not bound for HTTP GET requests. 通常,GET 请求只需一个记录 ID 参数。Typically, all you need for a GET request is a record ID parameter. 记录 ID 用于查找数据库中的项。The record ID is used to look up the item in the database. 因此,无需绑定包含模型实例的属性。Therefore, there is no need to bind a property that holds an instance of the model. 在需要将属性绑定到 GET 请求中的数据的情况下,请将 SupportsGet 属性设置为 trueIn scenarios where you do want properties bound to data from GET requests, set the SupportsGet property to true:

[BindProperty(Name ="ai_user", SupportsGet = true)]
public string ApplicationInsightsCookie { get; set; }

Sources

默认情况下,模型绑定以键值对的形式从 HTTP 请求中的以下源中获取数据:By default, model binding gets data in the form of key-value pairs from the following sources in an HTTP request:

  1. 表单域Form fields
  2. 请求正文(对于具有 [ApiController] 属性的控制器。)The request body (For controllers that have the [ApiController] attribute.)
  3. 路由数据Route data
  4. 查询字符串参数Query string parameters
  5. 上传的文件Uploaded files

对于每个目标参数或属性,将按此列表中指示的顺序扫描源。For each target parameter or property, the sources are scanned in the order indicated in this list. 有几个例外情况:There are a few exceptions:

  • 路由数据和查询字符串值仅用于简单类型。Route data and query string values are used only for simple types.
  • 上传的文件仅绑定到实现 IFormFileIEnumerable<IFormFile> 的目标类型。Uploaded files are bound only to target types that implement IFormFile or IEnumerable<IFormFile>.

如果默认行为没有给出正确结果,则可以使用以下某种属性来指定用于任意给定目标的源。If the default behavior doesn't give the right results, you can use one of the following attributes to specify the source to use for any given target.

这些属性:These attributes:

  • 分别添加到模型属性(而不是模型类),如以下示例所示:Are added to model properties individually (not to the model class), as in the following example:

    public class Instructor
    {
        public int ID { get; set; }
    
        [FromQuery(Name ="Note")]
        public string NoteFromQueryString { get; set; }
    
  • 选择性地在构造函数中接受模型名称值。Optionally accept a model name value in the constructor. 提供此选项的目的是应对属性名称与请求中的值不匹配的情况。This option is provided in case the property name doesn't match the value in the request. 例如,请求中的值可能是名称中带有连字符的标头,如以下示例所示:For instance, the value in the request might be a header with a hyphen in its name, as in the following example:

    public void OnGet([FromHeader(Name="Accept-Language")] string language)
    

[FromBody] 属性[FromBody] attribute

使用特定于请求内容类型的输入格式化程序来分析请求正文数据。The request body data is parsed by using input formatters specific to the content type of the request. 输入格式化程序的解释位于本文后面部分Input formatters are explained later in this article.

不要将 [FromBody] 应用于每个操作方法的多个参数。Don't apply [FromBody] to more than one parameter per action method. ASP.NET Core 运行时将读取请求流的责任委托给输入格式化程序。The ASP.NET Core runtime delegates the responsibility of reading the request stream to the input formatter. 读取请求流后,无法再次读取该请求来绑定其他 [FromBody] 参数。Once the request stream is read, it's no longer available to be read again for binding other [FromBody] parameters.

其他源Additional sources

源数据由“值提供程序”提供给模型绑定系统 。Source data is provided to the model binding system by value providers. 你可以编写并注册自定义值提供程序,这些提供程序从其他源中获取用于模型绑定的数据。You can write and register custom value providers that get data for model binding from other sources. 例如,你可能需要来自 Cookie 或会话状态的数据。For example, you might want data from cookies or session state. 要从新的源中获取数据,请执行以下操作:To get data from a new source:

  • 创建用于实现 IValueProvider 的类。Create a class that implements IValueProvider.
  • 创建用于实现 IValueProviderFactory 的类。Create a class that implements IValueProviderFactory.
  • Startup.ConfigureServices 中注册工厂类。Register the factory class in Startup.ConfigureServices.

示例应用包括从 Cookie 中获取值的 值提供程序工厂示例。The sample app includes a value provider and factory example that gets values from cookies. 以下是 Startup.ConfigureServices 中的注册代码:Here's the registration code in Startup.ConfigureServices:

services.AddMvc(options =>
{
    options.ValueProviderFactories.Add(new CookieValueProviderFactory());
    options.ModelMetadataDetailsProviders.Add(
        new ExcludeBindingMetadataProvider(typeof(System.Version)));
    options.ModelMetadataDetailsProviders.Add(
        new SuppressChildValidationMetadataProvider(typeof(System.Guid)));
})
.AddXmlSerializerFormatters()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

所示代码将自定义值提供程序置于所有内置值提供程序之后。The code shown puts the custom value provider after all the built-in value providers. 要将其置于列表中的首位,请调用 Insert(0, new CookieValueProviderFactory()) 而不是 AddTo make it the first in the list, call Insert(0, new CookieValueProviderFactory()) instead of Add.

不存在模型属性的源No source for a model property

默认情况下,如果找不到模型属性的值,则不会创建模型状态错误。By default, a model state error isn't created if no value is found for a model property. 该属性设置为 NULL 或默认值:The property is set to null or a default value:

  • 可以为 Null 的简单类型设置为 nullNullable simple types are set to null.
  • 不可以为 Null 的值类型设置为 default(T)Non-nullable value types are set to default(T). 例如,参数 int id 设置为 0。For example, a parameter int id is set to 0.
  • 对于复杂类型,模型绑定使用默认构造函数来创建实例,而不设置属性。For complex Types, model binding creates an instance by using the default constructor, without setting properties.
  • 数组设置为 Array.Empty<T>(),但 byte[] 数组设置为 nullArrays are set to Array.Empty<T>(), except that byte[] arrays are set to null.

如果在模型属性的表单域中找不到任何内容时,模型状态应无效,请使用 [BindRequired] 属性If model state should be invalidated when nothing is found in form fields for a model property, use the [BindRequired] attribute.

请注意,此 [BindRequired] 行为适用于发布的表单数据中的模型绑定,而不适用于请求正文中的 JSON 或 XML 数据。Note that this [BindRequired] behavior applies to model binding from posted form data, not to JSON or XML data in a request body. 请求正文数据由输入格式化程序进行处理。Request body data is handled by input formatters.

类型转换错误Type conversion errors

如果找到源,但无法将其转换为目标类型,则模型状态将被标记为无效。If a source is found but can't be converted into the target type, model state is flagged as invalid. 目标参数或属性设置为 NULL 或默认值,如上一部分所述。The target parameter or property is set to null or a default value, as noted in the previous section.

在具有 [ApiController] 属性的 API 控制器中,无效的模型状态会导致自动 HTTP 400 响应。In an API controller that has the [ApiController] attribute, invalid model state results in an automatic HTTP 400 response.

在 Razor Pages 中,重新显示带有错误消息的页面:In a Razor page, redisplay the page with an error message:

public IActionResult OnPost()
{
    if (!ModelState.IsValid)
    {
        return Page();
    }

    _instructorsInMemoryStore.Add(Instructor);
    return RedirectToPage("./Index");
}

客户端验证会捕获原本会提交到 Razor Pages 表单中的大多数错误数据。Client-side validation catches most bad data that would otherwise be submitted to a Razor Pages form. 此验证使得先前突出显示的代码难以被触发。This validation makes it hard to trigger the preceding highlighted code. 示例应用包含一个“提交无效日期”按钮,该按钮将错误数据置于“雇用日期”字段中并提交表单 。The sample app includes a Submit with Invalid Date button that puts bad data in the Hire Date field and submits the form. 此按钮显示在发生数据转换错误时用于重新显示页的代码将如何工作。This button shows how the code for redisplaying the page works when data conversion errors occur.

在使用先前的代码重新显示页时,表单域中不会显示无效的输入。When the page is redisplayed by the preceding code, the invalid input is not shown in the form field. 这是因为模型属性已设置为 NULL 或默认值。This is because the model property has been set to null or a default value. 无效输入会出现在错误消息中。The invalid input does appear in an error message. 但是,如果要在表单域中重新显示错误数据,可以考虑将模型属性设置为字符串并手动执行数据转换。But if you want to redisplay the bad data in the form field, consider making the model property a string and doing the data conversion manually.

如果不希望发生类型转换错误导致模型状态错误的情况,建议使用相同的策略。The same strategy is recommended if you don't want type conversion errors to result in model state errors. 在这种情况下,将模型属性设置为字符串。In that case, make the model property a string.

简单类型Simple types

模型绑定器可以将源字符串转换为以下简单类型:The simple types that the model binder can convert source strings into include the following:

复杂类型Complex types

复杂类型必须具有要绑定的公共默认构造函数和公共可写属性。A complex type must have a public default constructor and public writable properties to bind. 进行模型绑定时,将使用公共默认构造函数来实例化类。When model binding occurs, the class is instantiated using the public default constructor.

对于复杂类型的每个属性,模型绑定会查找名称模式 prefix.property_name 的源 。For each property of the complex type, model binding looks through the sources for the name pattern prefix.property_name. 如果未找到,它将仅查找不含前缀的 properties_name 。If nothing is found, it looks for just property_name without the prefix.

对于绑定到参数,前缀是参数名称。For binding to a parameter, the prefix is the parameter name. 对于绑定到 PageModel 公共属性,前缀是公共属性名称。For binding to a PageModel public property, the prefix is the public property name. 某些属性具有 Prefix 属性,让你可以替代参数或属性名称的默认用法。Some attributes have a Prefix property that lets you override the default usage of parameter or property name.

例如,假设复杂类型是以下 Instructor 类:For example, suppose the complex type is the following Instructor class:

public class Instructor
{
    public int ID { get; set; }
    public string LastName { get; set; }
    public string FirstName { get; set; }
}

前缀 = 参数名称Prefix = parameter name

如果要绑定的模型是一个名为 instructorToUpdate 的参数:If the model to be bound is a parameter named instructorToUpdate:

public IActionResult OnPost(int? id, Instructor instructorToUpdate)

模型绑定从查找键 instructorToUpdate.ID 的源开始操作。Model binding starts by looking through the sources for the key instructorToUpdate.ID. 如果未找到,它将查找不含前缀的 IDIf that isn't found, it looks for ID without a prefix.

前缀 = 属性名称Prefix = property name

如果要绑定的模型是控制器或 PageModel 类的一个名为 Instructor 的属性:If the model to be bound is a property named Instructor of the controller or PageModel class:

[BindProperty]
public Instructor Instructor { get; set; }

模型绑定从查找键 Instructor.ID 的源开始操作。Model binding starts by looking through the sources for the key Instructor.ID. 如果未找到,它将查找不含前缀的 IDIf that isn't found, it looks for ID without a prefix.

自定义前缀Custom prefix

如果要绑定的模型是名为 instructorToUpdate 的参数,并且 Bind 属性指定 Instructor 作为前缀:If the model to be bound is a parameter named instructorToUpdate and a Bind attribute specifies Instructor as the prefix:

public IActionResult OnPost(
    int? id, [Bind(Prefix = "Instructor")] Instructor instructorToUpdate)

模型绑定从查找键 Instructor.ID 的源开始操作。Model binding starts by looking through the sources for the key Instructor.ID. 如果未找到,它将查找不含前缀的 IDIf that isn't found, it looks for ID without a prefix.

复杂类型目标的属性Attributes for complex type targets

多个内置属性可用于控制复杂类型的模型绑定:Several built-in attributes are available for controlling model binding of complex types:

  • [BindRequired]
  • [BindNever]
  • [Bind]

备注

如果发布的表单数据是值的源,则这些属性会影响模型绑定。These attributes affect model binding when posted form data is the source of values. 它们不会影响处理发布的 JSON 和 XML 请求正文的输入格式化程序。They do not affect input formatters, which process posted JSON and XML request bodies. 输入格式化程序的解释位于本文后面部分Input formatters are explained later in this article.

另请参阅模型验证中针对 [Required] 属性的讨论。See also the discussion of the [Required] attribute in Model validation.

[BindRequired] 属性[BindRequired] attribute

只能应用于模型属性,不能应用于方法参数。Can only be applied to model properties, not to method parameters. 如果无法对模型属性进行绑定,则会导致模型绑定添加模型状态错误。Causes model binding to add a model state error if binding cannot occur for a model's property. 以下是一个示例:Here's an example:

public class InstructorWithCollection
{
    public int ID { get; set; }

    [DataType(DataType.Date)]
    [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
    [Display(Name = "Hire Date")]
    [BindRequired]
    public DateTime HireDate { get; set; }

[BindNever] 属性[BindNever] attribute

只能应用于模型属性,不能应用于方法参数。Can only be applied to model properties, not to method parameters. 防止模型绑定设置模型的属性。Prevents model binding from setting a model's property. 以下是一个示例:Here's an example:

public class InstructorWithDictionary
{
    [BindNever]
    public int ID { get; set; }

[Bind] 属性[Bind] attribute

可应用于类或方法参数。Can be applied to a class or a method parameter. 指定模型绑定中应包含的模型属性。Specifies which properties of a model should be included in model binding.

在下面的示例中,当调用任意处理程序或操作方法时,只绑定 Instructor 模型的指定属性:In the following example, only the specified properties of the Instructor model are bound when any handler or action method is called:

[Bind("LastName,FirstMidName,HireDate")]
public class Instructor

在下面的示例中,当调用 OnPost 方法时,只绑定 Instructor 模型的指定属性:In the following example, only the specified properties of the Instructor model are bound when the OnPost method is called:

[HttpPost]
public IActionResult OnPost([Bind("LastName,FirstMidName,HireDate")] Instructor instructor)

[Bind] 属性可用于防止“创建”方案中的过多发布情况 。The [Bind] attribute can be used to protect against overposting in create scenarios. 由于排除的属性设置为 NULL 或默认值,而不是保持不变,因此它在编辑方案中无法很好地工作。It doesn't work well in edit scenarios because excluded properties are set to null or a default value instead of being left unchanged. 为防止过多发布,建议使用视图模型,而不是使用 [Bind] 属性。For defense against overposting, view models are recommended rather than the [Bind] attribute. 有关详细信息,请参阅有关过多发布的安全性说明For more information, see Security note about overposting.

集合Collections

对于是简单类型集合的目标,模型绑定将查找 parameter_name 或 property_name 的匹配项 。For targets that are collections of simple types, model binding looks for matches to parameter_name or property_name. 如果找不到匹配项,它将查找某种不含前缀的受支持的格式。If no match is found, it looks for one of the supported formats without the prefix. 例如:For example:

  • 假设要绑定的参数是名为 selectedCourses 的数组:Suppose the parameter to be bound is an array named selectedCourses:

    public IActionResult OnPost(int? id, int[] selectedCourses)
    
  • 表单或查询字符串数据可以采用以下某种格式:Form or query string data can be in one of the following formats:

    selectedCourses=1050&selectedCourses=2000 
    
    selectedCourses[0]=1050&selectedCourses[1]=2000
    
    [0]=1050&[1]=2000
    
    selectedCourses[a]=1050&selectedCourses[b]=2000&selectedCourses.index=a&selectedCourses.index=b
    
    [a]=1050&[b]=2000&index=a&index=b
    
  • 只有表单数据支持以下格式:The following format is supported only in form data:

    selectedCourses[]=1050&selectedCourses[]=2000
    
  • 对于前面所有的示例格式,模型绑定将两个项的数组传递给 selectedCourses 参数:For all of the preceding example formats, model binding passes an array of two items to the selectedCourses parameter:

    • selectedCourses[0]=1050selectedCourses[0]=1050
    • selectedCourses[1]=2000selectedCourses[1]=2000

    使用下标数字的数据格式 (... [0] ... [1] ...) 必须确保从零开始按顺序进行编号。Data formats that use subscript numbers (... [0] ... [1] ...) must ensure that they are numbered sequentially starting at zero. 如果下标编号中存在任何间隔,则间隔后的所有项都将被忽略。If there are any gaps in subscript numbering, all items after the gap are ignored. 例如,如果下标是 0 和 2,而不是 0 和 1,则第二个项会被忽略。For example, if the subscripts are 0 and 2 instead of 0 and 1, the second item is ignored.

字典Dictionaries

对于 Dictionary 目标,模型绑定会查找 parameter_name 或 property_name 的匹配项 。For Dictionary targets, model binding looks for matches to parameter_name or property_name. 如果找不到匹配项,它将查找某种不含前缀的受支持的格式。If no match is found, it looks for one of the supported formats without the prefix. 例如:For example:

  • 假设目标参数是名为 selectedCoursesDictionary<int, string>Suppose the target parameter is a Dictionary<int, string> named selectedCourses:

    public IActionResult OnPost(int? id, Dictionary<int, string> selectedCourses)
    
  • 发布的表单或查询字符串数据可以类似于以下某一示例:The posted form or query string data can look like one of the following examples:

    selectedCourses[1050]=Chemistry&selectedCourses[2000]=Economics
    
    [1050]=Chemistry&selectedCourses[2000]=Economics
    
    selectedCourses[0].Key=1050&selectedCourses[0].Value=Chemistry&
    selectedCourses[1].Key=2000&selectedCourses[1].Value=Economics
    
    [0].Key=1050&[0].Value=Chemistry&[1].Key=2000&[1].Value=Economics
    
  • 对于前面所有的示例格式,模型绑定将两个项的字典传递给 selectedCourses 参数:For all of the preceding example formats, model binding passes a dictionary of two items to the selectedCourses parameter:

    • selectedCourses["1050"]="Chemistry"selectedCourses["1050"]="Chemistry"
    • selectedCourses["2000"]="Economics"selectedCourses["2000"]="Economics"

特殊数据类型Special data types

模型绑定可以处理某些特殊的数据类型。There are some special data types that model binding can handle.

IFormFile 和 IFormFileCollectionIFormFile and IFormFileCollection

HTTP 请求中包含的上传文件。An uploaded file included in the HTTP request. 还支持多个文件的 IEnumerable<IFormFile>Also supported is IEnumerable<IFormFile> for multiple files.

CancellationTokenCancellationToken

用于取消异步控制器中的活动。Used to cancel activity in asynchronous controllers.

FormCollectionFormCollection

用于从发布的表单数据中检索所有的值。Used to retrieve all the values from posted form data.

输入格式化程序Input formatters

请求正文中的数据可以是 JSON、XML 或其他某种格式。Data in the request body can be in JSON, XML, or some other format. 要分析此数据,模型绑定会使用配置为处理特定内容类型的输入格式化程序 。To parse this data, model binding uses an input formatter that is configured to handle a particular content type. 默认情况下,ASP.NET Core 包括用于处理 JSON 数据的基于 JSON 的输入格式化程序。By default, ASP.NET Core includes JSON based input formatters for handling JSON data. 可以为其他内容类型添加其他格式化程序。You can add other formatters for other content types.

ASP.NET Core 基于 Consumes 属性来选择输入格式化程序。ASP.NET Core selects input formatters based on the Consumes attribute. 如果没有属性,它将使用 Content-Type 标头If no attribute is present, it uses the Content-Type header.

要使用内置 XML 输入格式化程序,请执行以下操作:To use the built-in XML input formatters:

  • 安装 Microsoft.AspNetCore.Mvc.Formatters.Xml NuGet 包。Install the Microsoft.AspNetCore.Mvc.Formatters.Xml NuGet package.

  • Startup.ConfigureServices 中,调用 AddXmlSerializerFormattersAddXmlDataContractSerializerFormattersIn Startup.ConfigureServices, call AddXmlSerializerFormatters or AddXmlDataContractSerializerFormatters.

    services.AddMvc(options =>
    {
        options.ValueProviderFactories.Add(new CookieValueProviderFactory());
        options.ModelMetadataDetailsProviders.Add(
            new ExcludeBindingMetadataProvider(typeof(System.Version)));
        options.ModelMetadataDetailsProviders.Add(
            new SuppressChildValidationMetadataProvider(typeof(System.Guid)));
    })
    .AddXmlSerializerFormatters()
    .SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
    
  • Consumes 属性应用于应在请求正文中使用 XML 的控制器类或操作方法。Apply the Consumes attribute to controller classes or action methods that should expect XML in the request body.

    [HttpPost]
    [Consumes("application/xml")]
    public ActionResult<Pet> Create(Pet pet)
    

    有关更多信息,请参阅 XML 序列化简介For more information, see Introducing XML Serialization.

从模型绑定中排除指定类型Exclude specified types from model binding

模型绑定和验证系统的行为由 ModelMetadata 驱动。The model binding and validation systems' behavior is driven by ModelMetadata. 可通过向 MvcOptions.ModelMetadataDetailsProviders 添加详细信息提供程序来自定义 ModelMetadataYou can customize ModelMetadata by adding a details provider to MvcOptions.ModelMetadataDetailsProviders. 内置详细信息提供程序可用于禁用指定类型的模型绑定或验证。Built-in details providers are available for disabling model binding or validation for specified types.

要禁用指定类型的所有模型的模型绑定,请在 Startup.ConfigureServices 中添加 ExcludeBindingMetadataProviderTo disable model binding on all models of a specified type, add an ExcludeBindingMetadataProvider in Startup.ConfigureServices. 例如,禁用对 System.Version 类型的所有模型的模型绑定:For example, to disable model binding on all models of type System.Version:

services.AddMvc(options =>
{
    options.ValueProviderFactories.Add(new CookieValueProviderFactory());
    options.ModelMetadataDetailsProviders.Add(
        new ExcludeBindingMetadataProvider(typeof(System.Version)));
    options.ModelMetadataDetailsProviders.Add(
        new SuppressChildValidationMetadataProvider(typeof(System.Guid)));
})
.AddXmlSerializerFormatters()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

要禁用指定类型的属性的验证,请在 Startup.ConfigureServices 中添加 SuppressChildValidationMetadataProviderTo disable validation on properties of a specified type, add a SuppressChildValidationMetadataProvider in Startup.ConfigureServices. 例如,禁用对 System.Guid 类型的属性的验证:For example, to disable validation on properties of type System.Guid:

services.AddMvc(options =>
{
    options.ValueProviderFactories.Add(new CookieValueProviderFactory());
    options.ModelMetadataDetailsProviders.Add(
        new ExcludeBindingMetadataProvider(typeof(System.Version)));
    options.ModelMetadataDetailsProviders.Add(
        new SuppressChildValidationMetadataProvider(typeof(System.Guid)));
})
.AddXmlSerializerFormatters()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

自定义模型绑定器Custom model binders

通过编写自定义模型绑定器,并使用 [ModelBinder] 属性为给定目标选择该模型绑定器,可扩展模型绑定。You can extend model binding by writing a custom model binder and using the [ModelBinder] attribute to select it for a given target. 详细了解自定义模型绑定Learn more about custom model binding.

手动模型绑定Manual model binding

可以使用 TryUpdateModelAsync 方法手动调用模型绑定。Model binding can be invoked manually by using the TryUpdateModelAsync method. ControllerBasePageModel 类上均定义了此方法。The method is defined on both ControllerBase and PageModel classes. 方法重载允许指定要使用的前缀和值提供程序。Method overloads let you specify the prefix and value provider to use. 如果模型绑定失败,该方法返回 falseThe method returns false if model binding fails. 以下是一个示例:Here's an example:

if (await TryUpdateModelAsync<InstructorWithCollection>(
    newInstructor,
    "Instructor",
    i => i.FirstMidName, i => i.LastName, i => i.HireDate))
{
    _instructorsInMemoryStore.Add(newInstructor);
    return RedirectToPage("./Index");
}
PopulateAssignedCourseData(newInstructor);
return Page();

[FromServices] 属性[FromServices] attribute

此属性的名称遵循指定数据源的模型绑定属性的模式。This attribute's name follows the pattern of model binding attributes that specify a data source. 但这与绑定来自值提供程序的数据无关。But it's not about binding data from a value provider. 它从依赖关系注入容器中获取类型的实例。It gets an instance of a type from the dependency injection container. 其目的在于,在仅当调用特定方法时需要服务的情况下,提供构造函数注入的替代方法。Its purpose is to provide an alternative to constructor injection for when you need a service only if a particular method is called.

其他资源Additional resources