在Model绑定中,Model的数据来源有很多种,在MVC里面则定义了一套ValueProvider的组件来处理Model数据来源多样性的问题,ValueProvider整个结构类似于字典(Dictrionary)的键值结构,通过给定的Key来获取Value。在一整套的组件当中,有接口部分的,有实现接口的抽象ValueProvider及其子类,有ValueProvider的抽象工厂ValueProviderFactory以及其子类,有对所有ValueProviderFactory统一存放的集合等,类图如下,但蒋老师书上的类图好像有个地方标错了

接口部分

IValueProvider:声明GetValue方法和ContainsPrefix方法,前者根据key获得对应的Value,这个key有可能是带前缀的;后者是判断是否有给定前缀的key。

IEnumerableValueProvider:继承IValueProvider。针对目标类型为集合(Collection)的数据提供,生命了GetKeysFromPrefix方法,返回容器中具有指定前缀的Key,这个过程默认是需要验证的。

IUnvalidatedValueProvider:继承IValueProvider。声明了另外一个GetValue方法,这个方法不需要对数据作验证。

ValueProvider部分

ValueProviderResult:ValueProvider(凡是实现IValueProvider的类)的方法GetValue返回值的类型,其中AttemptedValue属性是Value的字符串形式表示;RawValue是Value的原始的值,这属性是Object类型;ConvertTo方法是按给定的Type类型转换,然后返回相应类型的对象,其一个重载方法是加上了CultrualInfo类型。

NameValueCollectionValueProvider:实现了IValueProvider,IEnumerableValueProvider和IUnValidatedValueProvider接口。在这个类中,key和value是以一种类似字典集合的形式存放,在这个集合中一个key可以有多个value,所以才说类似字典集合。Key和value都是string类型。


关于前缀,这里能用到前缀主要分两种场景

1是对于复杂类型的前缀,用完全限定名表示,例如书上的Contact类中的Address属性它是个Address类型,所以要表示Address类型中各个属性时,需要给各个属性多加一个“Address”前缀。

2对于绑定的同一类型多个Model时,为了区分不同实例的相同属性都会添加前缀,以作区分。前缀的形式有三种:1)以“对象名.”形式;2)以“[index].”形式;3)以”[对象名].“形式

在执行GetKeysFromPrefix时,方括号(”[“,”]“)和点(”.”)都有特殊含义,是占位符。


FormValueProvider:继承NameValueCollectionValueProvider,用于从提交的表单处提供数据。

QueryStringValueProvider:继承NameValueCollectionValueProvider,用于从URL(精确地说是QueryString)中提供数据。

DictionaryValueProvider<TValue>:实现了IEnumerableValueProvider和IValueProvider接口,里面key和value是真正的字典集合形式存放,key是string类型,value则是泛型。

RouteDataValueProvider:继承DictionaryValueProvider<object>,从路由参数中提供值。

HttpFileCollectionProvider:继承DictionaryValueProvider<HttpPostedFileBase[]>,Model中有HttpPostFileBase的数据提供者,通常有上传文件的Action会用到这个类,个人估计是每次发送请求就开辟一个key。

ChildActionValueProvider:继承DictionaryValueProvider<object>,处理子Action(子Action是在某个View中被调用生成某个部分的HTML,个人觉得是类似产生Partial View的Action)时提供值,与RouteDataValueProviderd都是以object为类型的value,同样从ControllerContext的Routedata提取值,Routedata的value(实际上是RouteValueDictionary类型)作为ChildActionValueProvider的数据容器字典,ChildActionValueProvider与RouteDataValueProvider的区别在于GetValue方法,RouteDataValueProvider是根据RouteValueDictionary的键值对去匹配,而ChildActionValueProvider是从它本身的字典集中,已一个GUID值作为key对应的value里面去取值,这个GUID是ChildActionValueProvider的一个静态属性,以这个key获取的value,本身是一个字典集,这个字典集的每一对key/value都存在于ChildActionValueProvider本身的键值对容器中,相当于以GUID为key的value作为了一个副本。至于为什么要这样做,本人也不太明白。

ValueProviderCollection:实现了IValueProvider,IEnumerableValueProvider和IUnValidatedValueProvider接口。是IValueProvider的一个集合,里面实现各个接口的方法,都是遍历调用集合里面各个元素的方法,具体的可以参照书上。

工厂部分

ValueProviderFactory:是一个抽象类,根据ControllerContext来创建各种ValueProvider。而具体的创建工作则由其子类去实现,这里就使用了工厂方法模式。

ValueProviderFactoryCollection:ValueProviderFactory的集合,定义了GetValueProvider方法,传入ControllerContext后各个ValueProviderFactory的同名方法都会被执行,谁先创建了就返回那种类型的工厂,这里就涉及到优先级问题,实际上就是集合中各个元素的顺序问题。

ValueProviderFactories:使用了ValueProviderFactoryCollection,为这个Collection集合实际填入元素的就是这个ValueProviderFactories,那些工厂的顺序是ChildActionValueProviderFactory,FormValueProviderFactory,JsonValueProviderFactory,RouteDataValueProviderFactory,QueryStringValueProviderFactory,HttpFileCollectionValueProviderFactory。

  对于这个ValueProvider组件,从整体结构来说使用了工厂方法模式,工厂方法的优点那些不必说了,从使用背景来看,Model的来源各式各样,具体提供值的规则可不需要组件核心来负责,规则可以自由扩充,那相应创建规则对象的创建者也留不得组件核心来操作,对组件核心来说只需要给了足够的信息,各种场景可以使用自己的一套方式,来创建出Model的值,这里需要提供的充足的信息,ControllerContext包含了请求信息和路由信息。

ASP.NET MVC ValueProvider小结的更多相关文章

  1. ASP.NET MVC ModelValidator小结

    当用户通过UI输入数据向程序交互时,都会出现一个潜在的错误,数据错误,要检查用户提交的数据是否正确,需要做数据验证,在ASP.NET MVC中,每当Action执行前都会对传入Action的Model ...

  2. 学习“迷你ASP.NET MVC框架”后的小结

    看蒋老师MVC的书第二个大收获可以是算是看了这个迷你ASP.NET MVC框架了,虽然它远不如真正ASP.NET MVC(下文简称“MVC”)那么复杂庞大,但在迷你版中绕来绕去也够呛的.这部分我看了几 ...

  3. ASP.NET MVC 下拉列表使用小结

    ASP.NET MVC中下拉列表的用法很简单,也很方便,具体来说,主要是页面上支持两种Html帮助类的方法:DropDownList()和DropDownListFor().这篇博文主要作为个人的一个 ...

  4. ASP.NET MVC 5入门小结

    1.前言        本人在读研究僧一只,老师那里使用的是ASP.NET的Web Forms技术,真的要感慨一句:尼玛太老旧了!之前耳闻Python的高效开发,曾经学过一点Python的Django ...

  5. 白话ASP.NET MVC之二:Controller激活系统的概览

    前文简介:我们抽象类路由规则的对象,RouteBase是路由对象的抽象基类,ASP.NET 的路由系统中有唯一一个从RouteBase继承的路由对象,那就是Route类型了.我们注册了路由对象Rout ...

  6. ASP.NET没有魔法——ASP.NET MVC 模型绑定解析(上篇)

    前面文章介绍了ASP.NET MVC中的模型绑定和验证功能,本着ASP.NET MVC没有魔法的精神,本章内容将从代码的角度对ASP.NET MVC如何完成模型的绑定和验证进行分析,已了解其原理. 本 ...

  7. ASP.NET没有魔法——ASP.NET MVC 模型绑定解析(下篇)

    上一篇<ASP.NET没有魔法——ASP.NET MVC 模型绑定解析(上篇)>文章介绍了ASP.NET MVC模型绑定的相关组件和概念,本章将介绍Controller在执行时是如何通过这 ...

  8. 【第三篇】ASP.NET MVC快速入门之安全策略(MVC5+EF6)

    目录 [第一篇]ASP.NET MVC快速入门之数据库操作(MVC5+EF6) [第二篇]ASP.NET MVC快速入门之数据注解(MVC5+EF6) [第三篇]ASP.NET MVC快速入门之安全策 ...

  9. 【番外篇】ASP.NET MVC快速入门之免费jQuery控件库(MVC5+EF6)

    目录 [第一篇]ASP.NET MVC快速入门之数据库操作(MVC5+EF6) [第二篇]ASP.NET MVC快速入门之数据注解(MVC5+EF6) [第三篇]ASP.NET MVC快速入门之安全策 ...

随机推荐

  1. ASP.NET一般处理程序访问Session问题

    我们在使用一般处理程序的时候,访问Session会出现如下错误: 解决方案如下: //引用命名空间 using System.Web.SessionState; //继承IRequiresSessio ...

  2. Javascript事件模型系列(四)我所理解的javascript自定义事件

    被我拖延了将近一个月的javascript事件模型系列终于迎来了第四篇,也是我计划中的最后一篇,说来太惭愧了,本来计划一到两个星期写完的,谁知中间遇到了很多事情,公司的个人的,搞的自己心烦意乱浮躁了一 ...

  3. 知方可补不足~用CDC功能来对数据库变更进行捕捉

    回到目录 如果我们希望监视一个数据表的变化,在sql2008之前的版本里,在数据库端可能想到的只有触发器,或者在程序端通过监视自己的insert,update,delete来实现相应的功能,这种实现无 ...

  4. 搭建jekyll博客

    使用jekyll将markdown文件生成静态的html文件,并使用主题有序的进行布局,形成最终的博客页面. 特点 基于ruby 使用Markdown书写文章 无需数据库 可以使用GitHub Pag ...

  5. Oracle Redo 以及 Archived日志简述

    Oracle通过Redo Archived实现数据的归档 什么是Redo日志 Redo日志记录了数据的变更,用于在数据库出现故障后,进行数据恢复. 功能主要由三个组件实现:Redo Log Buffe ...

  6. angularjs定义全局变量

    angularjs定义全局变量 三种方法 直接外层定义全局变量 利用ng的value定义全局变量 利用ng的constant定义全局变量 Takl is cheap, Show me the code ...

  7. 使用XSD校验Mybatis的SqlMapper配置文件(1)

    这篇文章以前面对SqlSessionFactoryBean的重构为基础,先简单回顾一下做了哪些操作: 新建SqlSessionFactoryBean,初始代码和mybatis-spring相同: 重构 ...

  8. 关于移动开发的一些想法和认识--Android和iOS

    微信公众账号很久没更新了,发一点自己最近的想法和内容. 之前和朋友做了一个项目,现在在跟一些风投,大公司里面的几家在谈合作和投资的事宜,从这个过程中也了解到了一些信息. 关于移动平台的应用开发与游戏开 ...

  9. 在Windows平台上安装Node.js及NPM模块管理

    1. 下载Node.js官方Windows版程序:http://nodejs.org/#download    从0.6.1开始,Node.js在Windows平台上提供了两种安装方式,一是.MSI安 ...

  10. Ubuntu 14.04上安装caffe

    本来实在windows 10上尝试安装caffe,装了一天没装上,放弃; 改在windows上装ubuntu的双系统,装了一个下午,不小心windows的系统盘被锁死了,也不会unlock?只好含泪卸 ...