8

我对模型绑定器如何在 ASP.Net MVC 中工作感到有些摸不着头脑。

具体来说,BindModel()方法有一个ModelBindingContext参数,里面保存着模型名称和类型,但是我不明白ModelBindingContext是怎么接收这些值的。

必须从发布的表单值或查询字符串参数或其他数据源填充 MVC 模型。但是什么机制决定了传递给 ModelBindingContext 的模型类型,以及如何选择一种模型类型而不是另一种模型类型,甚至(比如说)一个包含各个发布值的简单列表?

在我看来,ModelBindingContext“知道”它正在处理的模型类型,我不确定它来自哪里或填充它所涉及的工作流。

4

3 回答 3

15

有趣的问题。以下是 MVC 功能的简单概述。这一切都由 ControllerActionInovker 类处理。这不是特定的顺序,但很接近。

  1. ControllerActionInovker 通过反射确定参数类型。
  2. Next ValueProviders 是从 HttpContext Request Form、Route、QueryString 等属性创建的。您还可以提供自己的价值提供者。
  3. 这些 ValueProviders 通过充当虚拟 ValueProvider 的集合提供给 ModelBindingContext。
  4. 然后 ControllerActionInovker 查找特定类型的 ModelBinder。如果找不到,则默认为内置的 DefaultModelBinder。
  5. 在大多数情况下,使用 DefaultModelBinder。它的工作是创建一个模型,并使用 ValueProviders 使用模型属性名称作为键将属性与值连接起来。当 ValueProviders 有值时,它们返回一个负责类型转换的 ValueProviderResult 对象。

您可以在位于 codeplex.com 的 ASP.net MVC 源代码中亲自看到这一点。查找 ControllerActionInvoker 类和 GetParameterValue 方法。

于 2010-08-22T10:50:21.130 回答
3

ModelBindingContext “知道”它正在处理的模型类型,因为您必须:

  • 将 ModelBinder 属性添加到您的模型
  • 使用 ModelBinders.Binders.Add() 方法将 ModelBinder 注册到您的模型中。

ModelBinder 属性示例:

[ModelBinder(typeof(ContactBinder))]
public class Contact { ... }

ModelBinders.Binders.Add() 示例:

void Application_Start()
{
  ModelBinders.Binders[typeof(Contact)] = new ContactBinder();
}

如果您已经注册了 ModelBinder 并实现了 BindModel 方法:

public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) { ... }
  1. 查询 ModelBindingContext.ModelType 是否等于您的模型,例如

    if (bindingContext.ModelType == typeof(Contact)) { ... }
    
  2. 从 ModelBindingContext.ValueProvider 属性重新水化您的模型,以检索表示来自表单帖子、路由数据和查询字符串的数据的 ValueProviderResult 实例,例如

    bindingContext.ValueProvider["Name"].AttemptedValue;
    

以下书籍分别使用 了 ASP.NET MVC 2 in ActionASP.NET MVC 1.0 Quickly

于 2010-08-19T19:34:28.477 回答
1

我看到它的方式是 ControllerActionInvoker 使用反射来获取参数类型,然后它检查是否分配了任何 ModelBinder 来处理该类型,如果是,它实例化这个 ModelBinder 并将其传递给它 BindingContext 将包含(模型对象,模型该参数类型对象的名称、模型类型、属性过滤器)和所有其他值提供者(表单、查询字符串等)的值提供者集合 (ModelBindingContext.ValueProvider),充当一个大型虚拟值提供者。

然后,ModelBinder 本身使用反射来获取分配给其绑定的类型的所有属性名称,并针对 (ModelBindingContext.ValueProvider) 中的所有值提供者递归地运行自己,并在这些值提供者中查找属性名称,绑定那些为谁绑定的值。名称(取自客户端)与类型属性名称匹配,当它们匹配时,值提供者返回一个 ValueProviderResult 对象,其中包含模型上相应属性的名称和值。

于 2011-06-14T13:09:11.143 回答