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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Rgc

使用line_profiler查看api接口函数每行代码执行时间

项目情景描述:   在restful架构风格的项目交付测试的过程中,某接口出现 请求超时导致的http 502 Bad Gateway,于是开始排查具体是接口函...

4424
来自专栏大内老A

通过重建Hosting系统理解HTTP请求在ASP.NET Core管道中的处理流程[中]:管道如何处理请求

从上面的内容我们知道ASP.NET Core请求处理管道由一个服务器和一组中间件构成,所以从总体设计来讲是非常简单的。但是就具体的实现来说,由于其中涉及很多对象...

3039
来自专栏每日一篇技术文章

微信小程序_09 HTTPS

标准模板 var util = require('../../utils/util.js') wx.request({ url: 'https://URL...

2821
来自专栏软件工程师成长笔记

IE、FireFox、Chrome浏览器中关于URL传参中文乱码,解决兼容性问题!

前台用url传值中文,后台用request.getParameter接收参数。在Firefox,Chrome等浏览器中没有问题。但用IE浏览器就又会出现参数中文...

5272
来自专栏JavaQ

记一次java.lang.NoSuchMethodError

当思路如泉涌般、很流程的写完一段代码,点击Run看看执行结果的时候,Duang的一下输出了一串“Caused by: java.lang.NoSuchMetho...

42313
来自专栏布尔

学习利用JSON 摆脱表单与业务对象双向转换的繁琐工作

我想所有处理表单程序的同仁都会觉得很无聊,显示数据的时候要将业务对象一一绑定到表单,处理提交表单的时候要将包含在表单中的字段一个个再绑定到业务对象。这个过程很繁...

20110
来自专栏JetpropelledSnake

Django学习笔记之Django视图View

1563
来自专栏Kurt Niu 的博客

C# Int 类型线程不安全

之前统计报表算法做了一个优化,一个查询二十分钟导致客户端超时,优化到只需要5秒钟。后来发现for循环里数据合并的时候耗时,就用并行做优化。但是发现并行后丢居然数...

992
来自专栏walterlv - 吕毅的博客

生成代码,从 T 到 T1, T2, Tn —— 自动生成多个类型的泛型

发布于 2018-01-31 05:38 更新于 2018-05...

772
来自专栏JetpropelledSnake

Django学习笔记之Django中间件

1485

扫码关注云+社区

领取腾讯云代金券