在MVC框架中NameValueCollectionValueProvider采用一个NameValueCollection作为数据源,DictionnaryValueProvider的数据源类型自然就是一个Dictionnary。

NameValueCollection和Dictionnary都是一个键值对的集合,它们之间的不同之处在NameValueCollection运行元素具有相同的Key,Dictionnary却要求元素的Key具有唯一性。

DictionnaryValueProvider

在MVC框架默认的值提供程序中,ChildActionValueProvider,RouteDataValueProvider,HttpFileCollectionValueProvider等值提供程序都继承了DictionaryValueProvider类;

 public class DictionaryValueProvider<TValue> : IValueProvider, IEnumerableValueProvider
{
private PrefixContainer _prefixContainer;
private readonly Dictionary<string, ValueProviderResult> _values = new Dictionary<string, ValueProviderResult>(StringComparer.OrdinalIgnoreCase); public DictionaryValueProvider(IDictionary<string, TValue> dictionary, CultureInfo culture)
{
if (dictionary == null)
{
throw new ArgumentNullException("dictionary");
} foreach (KeyValuePair<string, TValue> entry in dictionary)
{
object rawValue = entry.Value;
string attemptedValue = Convert.ToString(rawValue, culture);
_values[entry.Key] = new ValueProviderResult(rawValue, attemptedValue, culture);
}
}
}

在DictionaryValueProvider的构造函数中接收一个key-value的字典类型,在函数内部逐个遍历这个字典类型,将每一项转换为ValueProviderResult类型,并以key-value的形式存储在Dictionary<string, ValueProviderResult> _values 中,在数据的查询都是在这个value字典里面进行查询;

DictionaryValueProvider类继承了IValueProvider和IEnumerableValueProvider接口;

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

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

 private PrefixContainer PrefixContainer
{
get
{
if (_prefixContainer == null)
{
_prefixContainer = new PrefixContainer(_values.Keys);
}
return _prefixContainer;
}
}
public virtual bool ContainsPrefix(string prefix)
{
return PrefixContainer.ContainsPrefix(prefix);
} public virtual ValueProviderResult GetValue(string key)
{
if (key == null)
{
throw new ArgumentNullException("key");
}
ValueProviderResult valueProviderResult;
_values.TryGetValue(key, out valueProviderResult);
return valueProviderResult;
}
public virtual IDictionary<string, string> GetKeysFromPrefix(string prefix)
{
return PrefixContainer.GetKeysFromPrefix(prefix);
}

DictionaryValueProvider类中的ContainsPrefix方法和GetKeysFromPrefix方法实际上是调用的PrefixContainer中的对应方法,在MVC框架中默认为PrefixContainer类;而GetValue根据key查找value字典的数据;因此DictionaryValueProvider类的作用实际上是做数据加工的作用,对应数据进行筛选的数据源来源于外部,通过构造方法的参数传入;

ChildActionValueProvider

public sealed class ChildActionValueProvider : DictionaryValueProvider<object>
{
private static string _childActionValuesKey = Guid.NewGuid().ToString();
public ChildActionValueProvider(ControllerContext controllerContext)
: base(controllerContext.RouteData.Values, CultureInfo.InvariantCulture)
{
}
}

ChildActionValueProvider专门服务于针对子Action方法参数的Model绑定。ChildActionValueProvider类在创建的过程中会把controllerContext.RouteData.Values坐位数据源传入到DictionaryValueProvider类中;但是在ChildActionValueProvider类中重写了DictionaryValueProvider类的GetValue方法;

 private static string _childActionValuesKey = Guid.NewGuid().ToString();
public override ValueProviderResult GetValue(string key)
{
if (key == null)
{
throw new ArgumentNullException("key");
}
ValueProviderResult explicitValues = base.GetValue(ChildActionValuesKey);
if (explicitValues != null)
{
DictionaryValueProvider<object> rawExplicitValues = explicitValues.RawValue as DictionaryValueProvider<object>;
if (rawExplicitValues != null)
{
return rawExplicitValues.GetValue(key);
}
}
return null;
}

当调用ChildActionValueProvider的GetValue方法获取指定Key的值时,实际上并不会直接根据指定的Key去获取对应的值,而是根据通过其静态字段_childActionValuesKey值去获取对应的DictionaryValueProvider<object>对象。然后再调用该对象的GetValue根据指定的Key去获得相应的值。

  RouteDataValueProvider

 public sealed class RouteDataValueProvider : DictionaryValueProvider<object>
{
public RouteDataValueProvider(ControllerContext controllerContext)
: base(controllerContext.RouteData.Values, CultureInfo.InvariantCulture)
{
}
}

RouteDataValueProvider类是将路由数据(controllerContext.RouteData.Values)做为数据源;

HttpFileCollectionValueProvider

 public sealed class HttpFileCollectionValueProvider : DictionaryValueProvider<HttpPostedFileBase[]>
{
private static readonly Dictionary<string, HttpPostedFileBase[]> _emptyDictionary = new Dictionary<string, HttpPostedFileBase[]>(); public HttpFileCollectionValueProvider(ControllerContext controllerContext)
: base(GetHttpPostedFileDictionary(controllerContext), CultureInfo.InvariantCulture)
{
}
private static Dictionary<string, HttpPostedFileBase[]> GetHttpPostedFileDictionary(ControllerContext controllerContext)
{
HttpFileCollectionBase files = controllerContext.HttpContext.Request.Files;
// fast-track common case of no files
if (files.Count == )
{
return _emptyDictionary;
}
List<KeyValuePair<string, HttpPostedFileBase>> mapping = new List<KeyValuePair<string, HttpPostedFileBase>>();
string[] allKeys = files.AllKeys;
for (int i = ; i < files.Count; i++)
{
string key = allKeys[i];
if (key != null)
{
HttpPostedFileBase file = HttpPostedFileBaseModelBinder.ChooseFileOrNull(files[i]);
mapping.Add(new KeyValuePair<string, HttpPostedFileBase>(key, file));
}
}
var grouped = mapping.GroupBy(el => el.Key, el => el.Value, StringComparer.OrdinalIgnoreCase);
return grouped.ToDictionary(g => g.Key, g => g.ToArray(), StringComparer.OrdinalIgnoreCase);
}

HttpFileCollectionValueProvider类是文件上传的的值提供程序,在HTTP请求的HttpRequestBase对象中,上传文件通过只读属性Files表示;在构造函数中通过GetHttpPostedFileDictionary方法创建一个key为文件名Value为HttpPostedFileBase类型的字典类型作为数据源;

MVC框架中的值提供机制(三)的更多相关文章

  1. MVC框架中的值提供机制(二)

    在MVC框架中存在一些默认的值提供程序模板,这些值提供程序都是通过工厂模式类创建;在MVC框架中存在需要已Factory结尾的工厂类,在值提供程序中也存在ValueProviderFactories工 ...

  2. MVC框架中的值提供机制(一)

    在MVC框架中action方法中的Model数据的绑定的来源有很多个,可能是http请求中的get参数或是post提交的表单数据,会是json字符串或是路径中的相关数据;MVC框架中针对这些不同的数据 ...

  3. [原]命令模式在MVC框架中的应用

    其实在项目开发中,我们使用了大量的设计模式,只是这些设计模式都封装在框架中了,如果你想要不仅仅局限于简单的使用,就应该深入了解框架的设计思路. 在MVC框架中,模式之一就是命令模式,先来看看模式是如何 ...

  4. 命令模式在MVC框架中的应用

    事实上在项目开发中,我们使用了大量的设计模式,不过这些设计模式都封装在框架中了,假设你想要不只局限于简单的使用,就应该深入了解框架的设计思路. 在MVC框架中,模式之中的一个就是命令模式,先来看看模式 ...

  5. MVC 框架中的缓存

    在程序中加入缓存的目的很多是为了提高程序的性能,提高数据的查找效率,在MVC框架中也引入了非常多的缓存,比如Controller的匹配查找,Controller,ControllerDescripto ...

  6. 找到MVC框架中前端URL与后端同步的解决方案

    基本思路: 先用URL标签生成完整的URL字符,前端动态参数的部分以适配符先填充,最后动态参数利用正则匹配进行替换. 这种方式,可以在各种MVC框架中适用,妙. 不废话,上码. var url = & ...

  7. asp.net MVC 框架中控制器里使用Newtonsoft.Json对前端传过来的字符串进行解析

    下面我用一个实例来和大家分享一下我的经验,asp.net MVC 框架中控制器里使用Newtonsoft.Json对前端传过来的字符串进行解析. using Newtonsoft.Json; usin ...

  8. 在ASP.NET MVC 框架中调用 html文件及解析get请求中的参数值

    在ASP.NET MVC 框架中调用 html文件: public ActionResult Index() { using (StreamReader sr = new StreamReader(P ...

  9. 前端控制器是整个MVC框架中最为核心的一块,它主要用来拦截符合要求的外部请求,并把请求分发到不同的控制器去处理,根据控制器处理后的结果,生成相应的响应发送到客户端。前端控制器既可以使用Filter实现(Struts2采用这种方式),也可以使用Servlet来实现(spring MVC框架)。

    本文转自http://www.cnblogs.com/davidwang456/p/4090058.html 感谢作者 前端控制器是整个MVC框架中最为核心的一块,它主要用来拦截符合要求的外部请求,并 ...

随机推荐

  1. 我的Android进阶之旅------>android Button上面的英文字符串自动大写的问题解决

    今天碰到一个关于Button的问题:android Button上面的英文字符串会自动变成大写,运行的Android 5.1版本,如下图所示: 图1:Button 图2:TextView 这个Butt ...

  2. 部署Node.js的应用

    原创:作者 mashihua 最近Node.js很火,让很多的前端看到了可以直接从前端写到后端的希望.但是每次部署一个Node.js的应用却让前端苦恼不已.每次登陆服务器,用自己不熟悉的方式从版本控制 ...

  3. 海量数据处理之Bloom Filter详解

    前言 :  即可能误判    不会漏判   一.什么是Bloom Filter     Bloom Filter是一种空间效率很高的随机数据结构,它的原理是,当一个元素被加入集合时,通过K个Hash函 ...

  4. JVM内存杂记1

    大多数 JVM 将内存区域划分为 Method Area(Non-Heap)(方法区) ,Heap(堆) , Program Counter Register(程序计数器) ,   VM Stack( ...

  5. [笔记]Go语言的字符串拼装方式性能对比

    Go语言中字符串的拼装方法很多,那么问题来了,到底哪家性能好? 下面代码,分别比较了 fmt.Sprintf,string +,strings.Join,bytes.Buffer,方法是循环若干次比较 ...

  6. JS中的正则应用

    如果还未掌握正则基础知识可先看另一篇:正则笔记-忘记就来看 创建方法: 直接量语法:/pattern/attributes 创建 RegExp 对象的语法:new RegExp(pattern, at ...

  7. ASC转换BCD,ASC2BCD(转)

    int ASC2BCD(const char* szASC,byte* szBDC)   {   int szASCLen=strlen(szASC);   byte * bpBCD = new by ...

  8. kali 2016:mount ntfs 分区只读 --Falling back to read-only mount because the NTFS partition is in an unsafe state.

    mount ntfs 分区 mount /dev/sdb1 /mnt/d 提示: The disk contains an unclean file system (0, 0).Metadata ke ...

  9. java判断集合list是为空

    if(null == list || list.size() ==0 ){ } list.isEmpty()和list.size()==0 没有区别 isEmpty()判断有没有元素而size()返回 ...

  10. Android Gradle 构建工具(Android Gradle Build Tools)是什么?

    转载地址:http://mrfu.me/android/2015/07/17/New_Android_Gradle_Build_Tools/ 译者地址:[翻]一览新的 Android Gradle 构 ...