ASP.NET MVC以ValueProvider为核心的值提供系统: ValueProviderFactory
在ASP.NET Model绑定系统中,用于提供数据值的ValueProvider对象通过ValueProviderFactory来创建。在ASP.NET MVC应用编程接口中,ValueProviderFactory继承自ValueProviderFactory类。本篇文章只要介绍基于ValueProviderFactory的ValueProvider的提供机制,以及如何通过自定义ValueProviderFactory实现我们需要的数据值的绑定方式。[本文已经同步到《How ASP.NET MVC Works?》中]
目录 一、ValueProviderFactory 二、ValueProviderFactory的注册 三、实例演示:创建一个自定义ValueProviderFactory
一、ValueProviderFactory
如下面的代码片断所示,ValueProviderFactory是一个抽象类,唯一的抽象方法GetValueProvider用于实现基于指定Controller上下文的ValueProvider创建。
1: public abstract class ValueProviderFactory
2: {
3: public abstract IValueProvider GetValueProvider(ControllerContext controllerContext);
4: }
下面的列表列出了定义在Model绑定系统中的6个原生的ValueProviderFactory:
- ChildActionValueProviderFactory:根据给定的Controller上下文创建一个ChildActionValueProvider对象。
- FormValueProviderFactory:根据给定的Controller上下文创建一个FormValueProvider对象。
- JsonValueProviderFactory:将以JSON形式表示的请求数据转换成一个Dictionary<string, object>对象,并最终创建一个DictionaryValueProvider<object>对象。
- RouteDataValueProviderFactory:根据给定的Controller上下文创建一个RouteDataValueProvider对象。
- QueryStringValueProviderFactory:根据给定的Controller上下文创建一个QueryStringValueProvider对象。
- HttpFileCollectionValueProviderFactory:根据给定的Controller上下文创建一个HttpFileCollectionValueProvider对象。
二、ValueProviderFactory的注册
ValueProviderFactory在ASP.NET MVC应用中的注册通过静态类型ValueProviderFactories实现。如下面的代码片断所示,ValueProviderFactories具有一个静态只读属性Factories返回一个表示ValueProviderFactory集合的ValueProviderFactoryCollection类型。
1: public static class ValueProviderFactories
2: {
3: public static ValueProviderFactoryCollection Factories { get; }
4: }
5:
6: public class ValueProviderFactoryCollection : Collection<ValueProviderFactory>
7: {
8: public ValueProviderFactoryCollection();
9: public ValueProviderFactoryCollection(IList<ValueProviderFactory> list);
10: public IValueProvider GetValueProvider(ControllerContext controllerContext);
11: }
ValueProviderFactoryCollection的GetValueProvider方法返回的是一个ValueProviderCollection对象,集合中的每个ValueProvider通过对应的ValueProviderFactory来创建。ValueProviderFactory在ValueProviderFactoryCollection集合中的先后次序决定了创建的ValueProvider在ValueProviderCollection中的次序,而次序决定了使用优先级。
在默认的情况下ValueProviderFactories的Factories属性表示的ValueProviderFactoryCollection包含了上面我们介绍的6种ValueProviderFactory,次序(优先级)为:ChildActionValueProviderFactory、FormValueProviderFactory、JsonValueProviderFactory、RouteDataValueProviderFactory、QueryStringValueProviderFactory和。如果具有相同的名称的请求书去同时存在于请求表单和查询字符串中,前者会被选用。
以ValueProvider为核心的值提供系统中涉及到了三类组件/类型,即用于具体实现数据值提供的ValueProvider,ValueProvider通过ValueProviderFactotry,而ValueProviderFactotry通过ValueProviderFactotries进行注册。图5-4所示的UML体现了三者之间的关系。
三、实例演示:创建一个自定义ValueProviderFactory
ASP.NET MVC提供的6种ValueProviderFactory基本上已经可以满足我们绝大部分Model绑定需求,不过对于一些比较极端的场景,我们有可能需要自定义ValueProviderFactory。作为演示,我们创建一个以HTTP请求报头集合作为数据源的自定义ValueProviderFactory。
我们将自定义的ValueProviderFactory命名为HttpHeaderValueProviderFactory。如下面的代码片断所示,HttpHeaderValueProviderFactory的定义非常简单,在重写的GetValueProvider方法中,我们将针对指定的Controller上下文得到HTTP报头集合,并借此创建NameValueCollection对象。由于作为报头名称具有“-”字符,为了与参数命名规则相匹配,我们将该字符剔除。最终创建的实际上是一个NameValueCollectionValueProvider对象。
1: public class HttpHeaderValueProviderFactory : ValueProviderFactory
2: {
3: public override IValueProvider GetValueProvider(ControllerContext controllerContext)
4: {
5: NameValueCollection requestData = new NameValueCollection();
6: var headers = controllerContext.RequestContext.HttpContext.Request.Headers;
7: foreach (string key in headers.Keys)
8: {
9: requestData.Add(key.Replace("-",""),headers[key]);
10: }
11: return new NameValueCollectionValueProvider(requestData, CultureInfo.InvariantCulture);
12: }
13: }
我们通过Visual Studio的ASP.NET MVC项目模板创建一个空Web应用,并创建一个具有如下定义的HomeController。默认的Action方法Index具有一系列的参数,从参数名称我们可以看出它们代表一些常用的HTTP报头。我们最终将代表HTTP报头的参数值呈现出来。
1: public class HomeController : Controller
2: {
3: public void Index(string connection, string accept, string acceptCharset, string acceptEncoding ,string acceptLanguage,
4: string host, string userAgent)
5: {
6: Response.Write(string.Format("{0}: {1}<br/>", "Connection", accept));
7: Response.Write(string.Format("{0}: {1}<br/>", "Accept-Charset", acceptCharset));
8: Response.Write(string.Format("{0}: {1}<br/>", "Accept Encoding", acceptEncoding));
9: Response.Write(string.Format("{0}: {1}<br/>", "Accept-Language", acceptLanguage));
10: Response.Write(string.Format("{0}: {1}<br/>", "Host", "host"));
11: Response.Write(string.Format("{0}: {1}<br/>", "User-Agent", userAgent));
12: }
13: }
然后利用Global.asax中按照如下的方式利用静态类型对我们自定义的HttpHeaderValueProviderFactory进行注册。
1: public class MvcApplication : System.Web.HttpApplication
2: {
3: //其他成员
4: protected void Application_Start()
5: {
6: //其他操作
7: ValueProviderFactories.Factories.Add(new HttpHeaderValueProviderFactory());
8: }
9: }
当我们运行该程序的时候,会在浏览器中呈现如下的输出结果,而输出的结果正是当前请求的HTTP报头列表。
1: Connection: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
2: Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
3: Accept Encoding: gzip,deflate,sdch
4: Accept-Language: en-US,en;q=0.8
5: Host: host
6: User-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.162 Safari/535.19
ASP.NET MVC以ValueProvider为核心的值提供系统: NameValueCollectionValueProvider ASP.NET MVC以ValueProvider为核心的值提供系统: DictionaryValueProvider ASP.NET MVC以ValueProvider为核心的值提供系统: ValueProviderFactory
- 在Windows上安装Jekyll
- 如何解决ajax跨域问题
- 基础篇章:React Native之 Image 的讲解
- 防守式编程的艺术
- Git 简单命令,木有高深内容
- 基础篇章:React Native之 ScrollView 的讲解
- 常用 Git 命令清单
- 如何将配置spring文件指定名字,指定位置
- 基础篇章:React Native 之 TextInput 的讲解
- Linux下 标准错误输出重定向
- CentOs6.5 修改主机名
- 基础篇章:React Native 之 View 和 Text 的讲解
- CentOs7.3 修改主机名
- 基础篇章:React Native之Flexbox的讲解(Height and Width)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法