模型绑定

响马 响马     2022-09-07     548

关键词:

  模型绑定主要是将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接口。  

 // 摘要: 
    //     定义 ASP.NET MVC 中的值提供程序所需的方法。
    public interface IValue

模型绑定

  模型绑定主要是将Http请求数据绑定到Action的参数中。模型绑定接口是IModelBinder  模型绑定器数据检测顺序:  1、检测目标对象的名称和类型。通常是动作方法的参数。  2、通过已知对象查找数据源(http请求),并... 查看详情

二十事件绑定及深入

...深入 事件绑定分为两种:一种是传统事件绑定(内联模型,脚本模型),一种是现代事件绑定(DOM2级模型)。现代事件绑定在传统绑定上提供了更强大更方便的功能。 1.传统事件绑定的问题传统事件绑定有内联模型和脚本模... 查看详情

模型绑定与验证笔记

模型绑定1.1模型绑定:以HTTP请求方式发送的数据来创建.NET对象的过程。每当定义具有参数的动作方法时,一直是在依赖着这种模型绑定过程 当导航到/Home/Index/1时,该URL的最后一个片段会被付给id路由变量,它指定了用户感... 查看详情

Umbraco 路由或模型绑定

】Umbraco路由或模型绑定【英文标题】:UmbracoRoutingorModelbinding【发布时间】:2020-02-2404:26:14【问题描述】:通过传递模型返回视图时遇到问题。errorMessage无法将源类型eCaptis.Models.Patient绑定到模型类型Umbraco.Core.Models.PublishedContent.IP... 查看详情

asp.netcore中的模型绑定

...,路由数据可以提供一个记录键,而发布的表单域可以为模型的属性提供一个值。编写代码以检索这些值,并将其从字符串转换为.NET类型不仅繁琐,而且还容易出错。模型绑定后会自动化该过程。模型绑定系统:假设有以下操... 查看详情

[十二]asp.netcore中的模型绑定(代码片段)

模型绑定1、模型绑定(1)HTTP请求数据2、ASP.NETCore中的模型验证(1)ModelState.IsValid属性验证(2)在视图中显示模型验证错误(3)自定义模型验证错误消息1、模型绑定模型绑定是将HTTP请求中的数据... 查看详情

[十二]asp.netcore中的模型绑定(代码片段)

模型绑定1、模型绑定(1)HTTP请求数据2、ASP.NETCore中的模型验证(1)ModelState.IsValid属性验证(2)在视图中显示模型验证错误(3)自定义模型验证错误消息1、模型绑定模型绑定是将HTTP请求中的数据... 查看详情

模型绑定不适用于嵌套对象

】模型绑定不适用于嵌套对象【英文标题】:Modelbindingnotworkingfornestedobject【发布时间】:2019-08-2711:26:34【问题描述】:我正在尝试在我的模型中绑定从邮递员发布的模型中的数据:publicclassVariantModelpublicintIdget;set;publicList<Subvar... 查看详情

Soap 服务模型绑定失败

】Soap服务模型绑定失败【英文标题】:SoapServiceModelBindingfailure【发布时间】:2021-02-2204:04:23【问题描述】:我有一个WCF肥皂服务。有一个带有模型参数的方法像这样:publicFirPrpsResRegPrps(FirPrpsReqPrpsReq)FirPrpsReq模型有另一个模型的... 查看详情

继承类型的 WebApi 模型绑定

】继承类型的WebApi模型绑定【英文标题】:WebApiModelBindingForInheritedTypes【发布时间】:2013-03-0901:37:45【问题描述】:我希望在WebApi中处理继承类型的模型绑定,而我真正想做的是使用默认模型绑定来处理绑定(除了选择无法这样... 查看详情

为啥重置表单不会清除绑定的模型属性

】为啥重置表单不会清除绑定的模型属性【英文标题】:Whyresettingaformdoesnotcleartheboundmodelattributes为什么重置表单不会清除绑定的模型属性【发布时间】:2017-12-2012:05:09【问题描述】:我已使用主干-stickitbindings将表单中的文本输... 查看详情

绑定 UITextField 以查看模型变量

】绑定UITextField以查看模型变量【英文标题】:BindUITextFieldtoviewmodelvariable【发布时间】:2017-09-0716:20:25【问题描述】:我正在尝试使用Bond将UI元素绑定到我的视图模型。当我尝试将searchTextField绑定到我的视图模型searchString时,Xco... 查看详情

模型绑定多个属性 SignalR

】模型绑定多个属性SignalR【英文标题】:ModelbindingmultiplepropertiesSignalR【发布时间】:2021-06-2117:06:33【问题描述】:我一直在一个新项目中试用SignalR,但在模型绑定方面遇到了问题。我的Javascript中心:state.socket?.invoke(SocketInvoke.s... 查看详情

js事件绑定及深入

...其他补充事件绑定分为两种:一种是传统事件绑定(内联模型,脚本模型),一种是现代事件绑定(DOM2级模型)。现代事件绑定在传统绑定上提供了更强大更方便的功能。一传统事件绑定的问题传统事件绑定中的内联模型不做... 查看详情

Laravel:使用路由/模型绑定时在表单请求中访问模型实例

】Laravel:使用路由/模型绑定时在表单请求中访问模型实例【英文标题】:Laravel:AccessModelinstanceinFormRequestwhenusingRoute/Modelbinding【发布时间】:2016-09-1718:17:04【问题描述】:我在我的项目中为我的一个模型设置了一些路由/模型绑... 查看详情

Laravel 路由绑定模型未定义偏移量:9

】Laravel路由绑定模型未定义偏移量:9【英文标题】:LaravelRouteBindingModelUndefinedoffset:9【发布时间】:2018-06-1219:47:07【问题描述】:我正在使用laravel5.2。我有一个名为Book的模型,然后尝试将路由绑定模型从我的控制器移动到RouteS... 查看详情

AngularJS 模型绑定在从

】AngularJS模型绑定在从【英文标题】:AngularJSmodelbindingbreakswhendeletedfrom【发布时间】:2014-03-0314:36:24【问题描述】:我正在构建一个AngularJS应用程序来创建多项选择测验。问题和相关选项被添加到以下模型中或从以下模型中删除... 查看详情

在 xml 聚合绑定中使用模型变量

】在xml聚合绑定中使用模型变量【英文标题】:Useamodelvariableinsidexmlaggregationbinding【发布时间】:2019-01-2505:20:54【问题描述】:我正在尝试使用带有过滤器的TreeTable绑定到OData。但是过滤器值在另一个模型中。这篇文章是关于XML... 查看详情