天天看点

ASP.NET MVC以ValueProvider为核心的值提供系统: NameValueCollectionValueProvider一、IValueProvider与ValueProviderResult二、NameValueCollectionValueProvider三、两种前缀形式四、实例演示:返回指定前缀的Key五、FormValueProvider与QueryStringValueProvider

在进行Model绑定过程中,需要根据基于Action方法参数的绑定上下文从请求数据中提取相应的数据以提供相应的数据。具体来说,Model绑定的数据具有多个来源,可能来源于Post的表单或者JSON字符串,或者来源于当前的路由数据,也可能来源于请求地址的插叙字符串。ASP.NET

目录 一、IValueProvider与ValueProviderResult 二、NameValueCollectionValueProvider 三、两种前缀形式 四、实例演示:返回指定前缀的Key 五、FormValueProvider与QueryStringValueProvider

ValueProviderResult提供了两个ConvertTo方法重载以实现向指定目标类型的转换。某些类型的格式化行为依赖于相应的语言文化(比如时间、日期和货币等),而这个辅助格式湖的语言文化信息通过Culture属性表示。其中第一个ValueProviderResult方法重载通过属性Culture表示的语言文化进行类型转化。

从上面的代码片断我们可以看到,除了IValueProvider接口,NameValueCollectionValueProvider还实现了IEnumerableValueProvider和IUnvalidatedValueProvider两个接口。顾名思义,IEnumerableValueProvider主要用于针对目标类型为集合的数据提供,方法GetKeysFromPrefix以一字典的形式返回具有指定前缀的Key。在默认的情况下,在进行数据提供的同时会对数据进行验证,而IUnvalidatedValueProvider接口提供了一个额外的GetValue方法是我们可以忽略对数据的验证。

由于NameValueCollection中每个元数据的值都是一个字符串,所以不可能单独表示一个复杂类型,复杂类型对象需要通过多个元素值组装而成。如果通过NameValueCollectionValueProvider来初始化一个完整的Contact对象,表示数据源的NameValueCollection至少需要包含7个元素,分别针对Contact除Address属性的三个属性值和作为Address的四个属性值,两类元素在NameValueCollection中通过基于属性的前缀来区分,具体的结构如下所示。

将点号(.)作为分隔符的前缀除了表示基于属性的层级关系之外,还可以用于数据筛选。如下面的代码片断所示,我们在ContactController中定义了一个用于添加联系人的AddContacts,它具有两个Contact类型的参数foo和bar,表示添加的两个不同的联系人。

如果我们采用NameValueCollectionValueProvider来提供作为AddContacts方法参数的两个Contact对象,保存在NameValueCollection的数据元素必须能够与它们进行合理映射。一般情况下这可以通过针对参数名的前缀来实现,具体数据结构如下所示。

除了采用基于“.”的前缀之外,数组或者集合类型的数据源元素可以采用基于“索引”的前缀,这样的前缀通过方括号“[]”表示,如下的数据结构就可以表示包含两个元素的Contact数组或者集合。

除了采用数字作为索引之前,我们还可以按照如下的方式通过文字作为索引。针对两种不同形式的索引的Model绑定机制有所不同,我们会在后续的部分予以讲述。

如果数据源元素针对不同的目标集合对象,同样需要采用相应的前缀予以区分,相面的数据结构可以看成是针对两个Contact列表(first和second)的数据源。

在了解两种不同类型的前缀之后,我们来关注一下NameValueCollectionValueProvider实现的GetKeysFromPrefix方法。从该方法的定义可以看出它返回的是一个IDictionary<string,

string>对象,但是这个对象具有怎样的数据呢?我们为此来进行一个实例演示。在通过Visual Studio的ASP.NET

MVC项目模板创建的空Web应用中,我们定义了如下一个默认的HomeController。在Action方法Index中我们创建了一个NameValueCollection对象,并针对它创建一个NameValueCollectionValueProvider.

通过上面的代码片断可以看出,作为NameValueCollectionValueProvider的数据元素是按照Contact类型的属性定义来添加的。我们分别将“foo”和“foo.Address”作为前缀返回以此作为前缀的Key。运行该程序后会在浏览器上得到如下的输出结果。我们可以看到对于针对指定前缀返回的字典对象,其Key和Value的不同之处在于前者没有包含指定的前缀而后者包含。此外,字典对象包含的元素全部处于同一级别,将“foo”指定为前缀时返回的元素针对于Contact的四个属性。虽然NameValueCollection中并不包含一个名为“foo.Address”的元素,但是依然会将其单独作为以“foo”为前缀的Key。

接下来我们采用相应的方式来演示基于索引的前缀,为此我们将HomeController的Index反方法进行了如下的改写。作为数据源的NameValueCollection对象针对一个包含两个元素的Contact集合,前缀“first”可以作为集合对象的名称。

我们分别针对三个前缀“first”、“first[0]”和“first[1]”获取相应字典对象并将其Key和Value呈现出来。该程序执行之后会在浏览器中产生如下的输出,如果我们将“[”和“]”视为和”.”一样的分割符,GetKeysFromPrefix针对索引作为前缀的规则与基于“.”前缀的规则没有本质的区别。

对于QueryStringValueProvider来说,无须多说,其作为数据源的NameValueCollection对象爱那个自然来源于请求的查询字符串,其定义基本上可以通过如下的代码表示(实际定义有所差异)。

<a href="http://www.cnblogs.com/artech/archive/2012/05/17/value-provider-01.html">ASP.NET MVC以ValueProvider为核心的值提供系统: NameValueCollectionValueProvider</a>

<a href="http://www.cnblogs.com/artech/archive/2012/05/18/value-provider-02.html">ASP.NET MVC以ValueProvider为核心的值提供系统: DictionaryValueProvider</a>

<a href="http://www.cnblogs.com/artech/archive/2012/05/19/value-provider-03.html">ASP.NET MVC以ValueProvider为核心的值提供系统: ValueProviderFactory</a>

作者:蒋金楠

微信公众账号:大内老A

如果你想及时得到个人撰写文章以及著作的消息推送,或者想看看个人推荐的技术资料,可以扫描左边二维码(或者长按识别二维码)关注个人公众号(原来公众帐号蒋金楠的自媒体将会停用)。

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

<a href="http://www.cnblogs.com/artech/archive/2012/05/17/value-provider-01.html" target="_blank">原文链接</a>