模型绑定

Posted 响马

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了模型绑定相关的知识,希望对你有一定的参考价值。

  模型绑定主要是将Http请求数据绑定到Action的参数中。模型绑定接口是IModelBinder

  模型绑定器数据检测顺序:

  1、检测目标对象的名称和类型。通常是动作方法的参数。

  2、通过已知对象查找数据源(http请求),并找到可用数据(字符串值)。

  3、根据对象的类型把可用数据值转换为目标类型。如果转换失败会报错误信息。

  4、通过已处理的数据来构造目标对象。

  5、将目标对象送到动作调用器,并由动作调用器将对象注入到目标动作方法中。

一、IModelBinder接口定义  

// 摘要: 
    //     定义模型联编程序所需的方法。
    public interface IModelBinder
    {
        // 摘要: 
        //     使用指定的控制器上下文和绑定上下文将模型绑定到一个值。
        //
        // 参数: 
        //   controllerContext:
        //     控制器上下文。
        //
        //   bindingContext:
        //     绑定上下文。
        //
        // 返回结果: 
        //     绑定值。
        object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext);
    }
View Code

二、默认模型绑定

  DefaultModelBinder是内奸的模型绑定器。默认绑定器查找参数的顺序为 Request.Form,RouteData.Values,Request.QueryString,Request.Files。

  模型绑定器处理数据类型转换时,如果转换失败会报错误信息。例如/person/edit/1,请求参数为int类型,改为/person/edid/jack,由jack转换为int时失败,那么通常情况下会报参数错误。

 

三、简单参数绑定

  简单参数绑定使用TypeConverter进行简单类型数据绑定。

四、复杂数据类型绑定

  复杂数据类型绑定,DefaultModelBinder使用反射获得公共属性然后再进行数据绑定。

五、手动调用模型绑定

  手动调用模型绑定使用UpdateModel和TryUpdateModel两种方法。两方法均是Controller中定义,并且均有不同类型的重载。   

   //
        // 摘要: 
        //     使用来自控制器的当前值提供程序的值更新指定的模型实例。
        //
        // 参数: 
        //   model:
        //     要更新的模型实例。
        //
        // 类型参数: 
        //   TModel:
        //     模型对象的类型。
        //
        // 返回结果: 
        //     如果更新已成功,则为 true;否则为 false。
        //
        // 异常: 
        //   System.ArgumentNullException:
        //     model 参数或 System.Web.Mvc.ControllerBase.ValueProvider 属性为 null。
        protected internal bool TryUpdateModel<TModel>(TModel model) where TModel : class;
        //
        // 摘要: 
        //     使用来自值提供程序的值更新指定的模型实例。
        //
        // 参数: 
        //   model:
        //     要更新的模型实例。
        //
        //   valueProvider:
        //     可用于更新模型的值字典。
        //
        // 类型参数: 
        //   TModel:
        //     模型对象的类型。
        //
        // 返回结果: 
        //     如果更新已成功,则为 true;否则为 false。
        protected internal bool TryUpdateModel<TModel>(TModel model, IValueProvider valueProvider) where TModel : class;
        //
        // 摘要: 
        //     使用来自控制器的当前值提供程序的值和前缀更新指定的模型实例。
        //
        // 参数: 
        //   model:
        //     要更新的模型实例。
        //
        //   prefix:
        //     在值提供程序中查找值时要使用的前缀。
        //
        // 类型参数: 
        //   TModel:
        //     模型对象的类型。
        //
        // 返回结果: 
        //     如果更新已成功,则为 true;否则为 false。
        //
        // 异常: 
        //   System.ArgumentNullException:
        //     model 参数或 System.Web.Mvc.ControllerBase.ValueProvider 属性为 null。
        protected internal bool TryUpdateModel<TModel>(TModel model, string prefix) where TModel : class;
        //
        // 摘要: 
        //     使用来自控制器的当前值提供程序的值和包含的属性更新指定的模型实例。
        //
        // 参数: 
        //   model:
        //     要更新的模型实例。
        //
        //   includeProperties:
        //     一个要更新的模型的属性列表。
        //
        // 类型参数: 
        //   TModel:
        //     模型对象的类型。
        //
        // 返回结果: 
        //     如果更新已成功,则为 true;否则为 false。
        //
        // 异常: 
        //   System.ArgumentNullException:
        //     model 参数或 System.Web.Mvc.ControllerBase.ValueProvider 属性为 null。
        protected internal bool TryUpdateModel<TModel>(TModel model, string[] includeProperties) where TModel : class;
        //
        // 摘要: 
        //     使用来自值提供程序的值和前缀更新指定的模型实例。
        //
        // 参数: 
        //   model:
        //     要更新的模型实例。
        //
        //   prefix:
        //     在值提供程序中查找值时要使用的前缀。
        //
        //   valueProvider:
        //     可用于更新模型的值字典。
        //
        // 类型参数: 
        //   TModel:
        //     模型对象的类型。
        //
        // 返回结果: 
        //     如果更新已成功,则为 true;否则为 false。
        protected internal bool TryUpdateModel<TModel>(TModel model, string prefix, IValueProvider valueProvider) where TModel : class;
        //
        // 摘要: 
        //     使用来自控制器的当前值提供程序的值、前缀和包含的属性更新指定的模型实例。
        //
        // 参数: 
        //   model:
        //     要更新的模型实例。
        //
        //   prefix:
        //     在值提供程序中查找值时要使用的前缀。
        //
        //   includeProperties:
        //     一个要更新的模型的属性列表。
        //
        // 类型参数: 
        //   TModel:
        //     模型对象的类型。
        //
        // 返回结果: 
        //     如果更新已成功,则为 true;否则为 false。
        //
        // 异常: 
        //   System.ArgumentNullException:
        //     model 参数或 System.Web.Mvc.ControllerBase.ValueProvider 属性为 null。
        protected internal bool TryUpdateModel<TModel>(TModel model, string prefix, string[] includeProperties) where TModel : class;
        //
        // 摘要: 
        //     使用来自值提供程序的值和要包含的属性列表更新指定的模型实例。
        //
        // 参数: 
        //   model:
        //     要更新的模型实例。
        //
        //   includeProperties:
        //     一个要更新的模型的属性列表。
        //
        //   valueProvider:
        //     可用于更新模型的值字典。
        //
        // 类型参数: 
        //   TModel:
        //     模型对象的类型。
        //
        // 返回结果: 
        //     如果更新已成功,则为 true;否则为 false。
        protected internal bool TryUpdateModel<TModel>(TModel model, string[] includeProperties, IValueProvider valueProvider) where TModel : class;
        //
        // 摘要: 
        //     使用来自值提供程序的值、前缀和包含的属性更新指定的模型实例。
        //
        // 参数: 
        //   model:
        //     要更新的模型实例。
        //
        //   prefix:
        //     在值提供程序中查找值时要使用的前缀。
        //
        //   includeProperties:
        //     一个要更新的模型的属性列表。
        //
        //   valueProvider:
        //     可用于更新模型的值字典。
        //
        // 类型参数: 
        //   TModel:
        //     模型对象的类型。
        //
        // 返回结果: 
        //     如果更新已成功,则为 true;否则为 false。
        protected internal bool TryUpdateModel<TModel>(TModel model, string prefix, string[] includeProperties, IValueProvider valueProvider) where TModel : class;
        //
        // 摘要: 
        //     使用来自控制器的当前值提供程序的值、前缀、要排除的属性列表和要包含的属性列表更新指定的模型实例。
        //
        // 参数: 
        //   model:
        //     要更新的模型实例。
        //
        //   prefix:
        //     在值提供程序中查找值时要使用的前缀
        //
        //   includeProperties:
        //     一个要更新的模型的属性列表。
        //
        //   excludeProperties:
        //     要从该更新中显式排除的属性列表。即使 includeProperties 参数列表中列出了这些属性,也会将其排除。
        //
        // 类型参数: 
        //   TModel:
        //     模型对象的类型。
        //
        // 返回结果: 
        //     如果更新已成功,则为 true;否则为 false。
        //
        // 异常: 
        //   System.ArgumentNullException:
        //     model 参数或 System.Web.Mvc.ControllerBase.ValueProvider 属性为 null。
        protected internal bool TryUpdateModel<TModel>(TModel model, string prefix, string[] includeProperties, string[] excludeProperties) where TModel : class;
        //
        // 摘要: 
        //     使用来自值提供程序的值、前缀、要排除的属性列表和要包含的属性列表更新指定的模型实例。
        //
        // 参数: 
        //   model:
        //     要更新的模型实例。
        //
        //   prefix:
        //     在值提供程序中查找值时要使用的前缀。
        //
        //   includeProperties:
        //     一个要更新的模型的属性列表。
        //
        //   excludeProperties:
        //     要从该更新中显式排除的属性列表。即使 includeProperties 参数列表中列出了这些属性,也会将其排除。
        //
        //   valueProvider:
        //     可用于更新模型的值字典。
        //
        // 类型参数: 
        //   TModel:
        //     模型对象的类型。
        //
        // 返回结果: 
        //     如果更新已成功,则为 true;否则为 false。
        protected internal bool TryUpdateModel<TModel>(TModel model, string prefix, string[] includeProperties, string[] excludeProperties, IValueProvider valueProvider) where TModel : class;
View Code

 

//
        // 摘要: 
        //     使用来自控制器的当前值提供程序的值更新指定的模型实例。
        //
        // 参数: 
        //   model:
        //     要更新的模型实例。
        //
        // 类型参数: 
        //   TModel:
        //     模型对象的类型。
        //
        // 异常: 
        //   System.InvalidOperationException:
        //     此模型没有成功更新。
        protected internal void UpdateModel<TModel>(TModel model) where TModel : class;
        //
        // 摘要: 
        //     使用来自值提供程序的值更新指定的模型实例。
        //
        // 参数: 
        //   model:
        //     要更新的模型实例。
        //
        //   valueProvider:
        //     可用于更新模型的值字典。
        //
        // 类型参数: 
        //   TModel:
        //     模型对象的类型。
        protected internal void UpdateModel<TModel>(TModel model, IValueProvider valueProvider) where TModel : class;
        //
        // 摘要: 
        //     使用来自控制器的当前值提供程序的值和前缀更新指定的模型实例。
        //
        // 参数: 
        //   model:
        //     要更新的模型实例。
        //
        //   prefix:
        //     在值提供程序中查找值时要使用的前缀。
        //
        // 类型参数: 
        //   TModel:
        //     模型对象的类型。
        protected internal void UpdateModel<TModel>(TModel model, string prefix) where TModel : class;
        //
        // 摘要: 
        //     使用来自控制器对象的当前值提供程序的值更新指定的模型实例。
        //
        // 参数: 
        //   model:
        //     要更新的模型实例。
        //
        //   includeProperties:
        //     一个要更新的模型的属性列表。
        //
        // 类型参数: 
        //   TModel:
        //     模型对象的类型。
        protected internal void UpdateModel<TModel>(TModel model, string[] includeProperties) where TModel : class;
        //
        // 摘要: 
        //     使用来自值提供程序的值和前缀更新指定的模型实例。
        //
        // 参数: 
        //   model:
        //     要更新的模型实例。
        //
        //   prefix:
        //     在值提供程序中查找值时要使用的前缀。
        //
        //   valueProvider:
        //     可用于更新模型的值字典。
        //
        // 类型参数: 
        //   TModel:
        //     模型对象的类型。
        protected internal void UpdateModel<TModel>(TModel model, string prefix, IValueProvider valueProvider) where TModel : class;
        //
        // 摘要: 
        //     使用来自控制器的当前值提供程序的值、前缀和包含的属性更新指定的模型实例。
        //
        // 参数: 
        //   model:
        //     要更新的模型实例。
        //
        //   prefix:
        //     在值提供程序中查找值时要使用的前缀。
        //
        //   includeProperties:
        //     一个要更新的模型的属性列表。
        //
        // 类型参数: 
        //   TModel:
        //     模型对象的类型。
        protected internal void UpdateModel<TModel>(TModel model, string prefix, string[] includeProperties) where TModel : class;
        //
        // 摘要: 
        //     使用来自值提供程序的值、前缀和要包含的属性列表更新指定的模型实例。
        //
        // 参数: 
        //   model:
        //     要更新的模型实例。
        //
        //   includeProperties:
        //     一个要更新的模型的属性列表。
        //
        //   valueProvider:
        //     可用于更新模型的值字典。
        //
        // 类型参数: 
        //   TModel:
        //     模型对象的类型。
        protected internal void UpdateModel<TModel>(TModel model, string[] includeProperties, IValueProvider valueProvider) where TModel : class;
        //
        // 摘要: 
        //     使用来自值提供程序的值、前缀和要包含的属性列表更新指定的模型实例。
        //
        // 参数: 
        //   model:
        //     要更新的模型实例。
        //
        //   prefix:
        //     在值提供程序中查找值时要使用的前缀。
        //
        //   includeProperties:
        //     一个要更新的模型的属性列表。
        //
        //   valueProvider:
        //     可用于更新模型的值字典。
        //
        // 类型参数: 
        //   TModel:
        //     模型对象的类型。
        protected internal void UpdateModel<TModel>(TModel model, string prefix, string[] includeProperties, IValueProvider valueProvider) where TModel : class;
        //
        // 摘要: 
        //     使用来自控制器的当前值提供程序的值、前缀、要排除的属性列表和要包含的属性列表更新指定的模型实例。
        //
        // 参数: 
        //   model:
        //     要更新的模型实例。
        //
        //   prefix:
        //     在值提供程序中查找值时要使用的前缀。
        //
        //   includeProperties:
        //     一个要更新的模型的属性列表。
        //
        //   excludeProperties:
        //     要从该更新中显式排除的属性列表。即使 includeProperties 列表中列出了这些属性,也会将其排除。
        //
        // 类型参数: 
        //   TModel:
        //     模型对象的类型。
        protected internal void UpdateModel<TModel>(TModel model, string prefix, string[] includeProperties, string[] excludeProperties) where TModel : class;
        //
        // 摘要: 
        //     使用来自值提供程序的值、前缀、要排除的属性列表和要包含的属性列表更新指定的模型实例。
        //
        // 参数: 
        //   model:
        //     要更新的模型实例。
        //
        //   prefix:
        //     在值提供程序中查找值时要使用的前缀。
        //
        //   includeProperties:
        //     一个要更新的模型的属性列表。
        //
        //   excludeProperties:
        //     要从该更新中显式排除的属性列表。即使 includeProperties 参数列表中列出了这些属性,也会将其排除。
        //
        //   valueProvider:
        //     可用于更新模型的值字典。
        //
        // 类型参数: 
        //   TModel:
        //     模型对象的类型。
        protected internal void UpdateModel<TModel>(TModel model, string prefix, string[] includeProperties, string[] excludeProperties, IValueProvider valueProvider) where TModel : class;
View Code

  两种手动模型绑定方式如果出现错误是均可以使用ModelState.IsValide来查看是否有错误。 

 在实际中常用的是FormCollection,因为FormCollection实现了IValueProvider接口。  

// 摘要: 
    //     包含应用程序的窗体值提供程序。
    public sealed class FormCollection : NameValueCollection, IValueProvider
    {
        // 摘要: 
        //     初始化 System.Web.Mvc.FormCollection 类的新实例。
        public FormCollection();
        //
        // 摘要: 
        //     初始化 System.Web.Mvc.FormCollection 类的新实例。
        //
        // 参数: 
        //   collection:
        //     集合。
        //
        // 异常: 
        //   System.ArgumentNullException:
        //     collection 参数为 null。
        public FormCollection(NameValueCollection collection);

        // 摘要: 
        //     获取指定的值提供程序。
        //
        // 参数: 
        //   name:
        //     要获取的值提供程序的名称。
        //
        // 返回结果: 
        //     值提供程序。
        //
        // 异常: 
        //   System.ArgumentException:
        //     name 参数为 null 或为空。
        public ValueProviderResult GetValue(string name);
        //
        // 摘要: 
        //     返回包含值提供程序的字典。
        //
        // 返回结果: 
        //     值提供程序的字典。
        public IValueProvider ToValueProvider();
    }
View Code

 

六、创建自定义IValueProvider

  创建自定义值提供器,需要实现IValueProvider接口。