什么是模型绑定
控制器和 Razor Pages 处理来自 HTTP 请求的数据。 例如,路由数据可以提供一个记录键,而发布的表单域可以为模型的属性提供一个值。 编写代码以检索这些值,并将其从字符串转换为 .NET 类型不仅繁琐,而且还容易出错。 模型绑定会自动化该过程。 模型绑定系统:
- 从各种源(如路由数据、表单域和查询字符串)中检索数据。
- 将数据提供给方法参数和公共属性中的控制器和 Razor Pages。
- 将字符串数据转换为 .NET 类型。
- 更新复杂类型的属性。
示例
假设有以下操作方法:
[HttpGet("{id}")]
public ActionResult<Pet> GetById(int id, bool dogsOnly)
并且应用收到一个带有以下 URL 的请求:
https://contoso.com/api/pets/2?DogsOnly=true
在路由系统选择该操作方法之后,模型绑定执行以下步骤:
- 查找
GetById
的第一个参数,该参数是一个名为id
的整数。 - 查找 HTTP 请求中的可用源,并在路由数据中查找
id
=“2”。 - 将字符串“2”转换为整数 2。
- 查找
GetById
的下一个参数,该参数是一个名为dogsOnly
的布尔值。 - 查找源,并在查询字符串中查找“DogsOnly=true”。 名称匹配不区分大小写。
- 将字符串“true”转换为布尔值
true
。
然后,该框架会调用 GetById
方法,为 id
参数传入 2,并为 dogsOnly
参数传入 true。
目标
模型绑定尝试查找以下类型目标的值:
- 将请求路由到的控制器操作方法的参数。
- 请求路由到的 Razor Pages 处理程序方法的参数。
- 控制器或
PageModel
类的公共属性(若由特性指定)。
[BindProperty] 属性
可应用于控制器或 PageModel
类的公共属性,从而使模型绑定以该属性为目标
[BindProperties] 属性
可应用于控制器或 PageModel
类,以使模型绑定以该类的所有公共属性为目标
HTTP GET 请求的模型绑定
默认情况下,不绑定 HTTP GET 请求的属性。 通常,GET 请求只需一个记录 ID 参数。 记录 ID 用于查找数据库中的项。 因此,无需绑定包含模型实例的属性。 在需要将属性绑定到 GET 请求中的数据的情况下,请将 SupportsGet
属性设置为 true
[BindProperty(Name = "ai_user", SupportsGet = true)]
public string? ApplicationInsightsCookie { get; set; }
源
默认情况下,模型绑定以键值对的形式从 HTTP 请求中的以下源中获取数据:
- 表单域
- 请求正文(对于具有 [ApiController] 属性的控制器。)
- 路由数据
- 查询字符串参数
- 上传的文件
对于每个目标参数或属性,按照之前列表中指示的顺序扫描源。 有几个例外情况:
- 路由数据和查询字符串值仅用于简单类型。
- 上传的文件仅绑定到实现
IFormFile
或IEnumerable<IFormFile>
的目标类型。
如果默认源不正确,请使用下列属性之一来指定源:
- [FromQuery] - 从查询字符串中获取值。
- [FromRoute] - 从路由数据中获取值。
- [FromForm] - 从发布的表单域中获取值。
- [FromBody] - 从请求正文中获取值。
- [FromHeader] - 从 HTTP 标头中获取值。
[FromBody] 属性
将 [FromBody]
特性应用于一个参数,以便从一个 HTTP 请求的正文填充其属性。 ASP.NET Core 运行时将读取正文的责任委托给输入格式化程序。
将 [FromBody]
应用于复杂类型参数时,应用于其属性的任何绑定源属性都将被忽略。 例如,以下 Create
操作指定从正文填充其 pet
参数:
public ActionResult<Pet> Create([FromBody] Pet pet)
Pet
类指定从查询字符串参数填充其 Breed
属性:
public class Pet
{
public string Name { get; set; } = null!;
[FromQuery] // Attribute is ignored.
public string Breed { get; set; } = null!;
}
在上面的示例中:
[FromQuery]
特性被忽略。Breed
属性未从查询字符串参数进行填充。
输入格式化程序只读取正文,不了解绑定源特性。 如果在正文中找到合适的值,则使用该值填充 Breed
属性。
不要将 [FromBody]
应用于每个操作方法的多个参数。 输入格式化程序读取请求流后,无法再次读取该流以绑定其他 [FromBody]
参数。
其他源
源数据由“值提供程序”提供给模型绑定系统。 你可以编写并注册自定义值提供程序,这些提供程序从其他源中获取用于模型绑定的数据。 例如,你可能需要来自 cookie 或会话状态的数据。 要从新的源中获取数据,请执行以下操作:
- 创建用于实现
IValueProvider
的类。 - 创建用于实现
IValueProviderFactory
的类。 - 在
Program.cs
中注册工厂类。