<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title type="text">博客园_Artech</title><subtitle type="text"/><id>http://feed.cnblogs.com/blog/u/22886/rss</id><updated>2012-05-28T01:51:58Z</updated><author><name>Artech</name><uri>http://www.cnblogs.com/artech/</uri></author><generator>feed.cnblogs.com</generator><link rel="alternate" type="text/html" href="http://www.cnblogs.com/artech/"/><link rel="self" type="application/atom+xml" href="http://feed.cnblogs.com/blog/u/22886/rss"/><entry><id>http://www.cnblogs.com/artech/archive/2012/05/23/default-model-binding-01.html</id><title type="text">通过实例模拟ASP.NET MVC的Model绑定机制[上篇]</title><summary type="text">总的来说，针对目标Action方法参数的Model绑定完全由组件ModelBinder来实现，在默认情况下使用的ModelBinder类型为DefaultModelBinder，接下来我们将按照逐层深入的方式通过一个模拟程序来介绍实现在DefaultModelBinder的默认Model绑定机制。</summary><published>2012-05-23T00:20:00Z</published><updated>2012-05-23T00:20:00Z</updated><author><name>Artech</name><uri>http://www.cnblogs.com/artech/</uri></author><link rel="alternate" href="http://www.cnblogs.com/artech/archive/2012/05/23/default-model-binding-01.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/artech/archive/2012/05/23/default-model-binding-01.html"/><content type="html">&lt;p&gt;总的来说，针对目标Action方法参数的Model绑定完全由组件ModelBinder来实现，在默认情况下使用的ModelBinder类型为&lt;a title="DefaultModelBinder Class" href="http://msdn2.microsoft.com/dd470193.aspx"&gt;DefaultModelBinder&lt;/a&gt;，接下来我们将按照逐层深入的方式介绍实现在DefaultModelBinder的默认Model绑定机制。[源代码从&lt;a href="http://files.cnblogs.com/artech/S520.rar"&gt;这里&lt;/a&gt;下载][本文已经同步到《&lt;a href="http://www.cnblogs.com/artech/archive/2012/04/10/how-mvc-works.html"&gt;How ASP.NET MVC Works?&lt;/a&gt;》中]&lt;/p&gt;  &lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;   &lt;p&gt;目录      &lt;br /&gt;一、简单类型       &lt;br /&gt;二、复杂类型       &lt;br /&gt;三、数组       &lt;br /&gt;四、集合       &lt;br /&gt;五、字典&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;strong&gt;&lt;font size="4"&gt;&lt;font style="font-weight: bold"&gt;一、简单类型&lt;/font&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;对于旨在绑定目标Action方法参数值的Model来说，最简单的莫过于简单参数类型的情况。通过《&lt;a href="http://www.cnblogs.com/artech/archive/2012/04/11/model-metadata-01.html"&gt;初识Model元数据&lt;/a&gt;》的介绍我们知道，复杂类型和简单类型之间的区别仅仅在于是否支持针对字符串类型的转换。由于参数值的数据源在请求中以字符串的形式存在，对于支持字符串转换的简单类型来说，可以直接通过类型转换得到参数值。我们通过一个简单的实例来模拟实现在DefaultModelBinder中针对简单类型的Model绑定。如下所示的是我们自定义的DefaultModelBinder，其属性ValueProvider用于从请求中提供相应的数据值，该属性在构造函数中被初始化。&lt;/p&gt;  &lt;div id="codeSnippetWrapper"&gt;   &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;     &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; DefaultModelBinder&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; IValueProvider ValueProvider { get; &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; set; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; DefaultModelBinder(IValueProvider valueProvider)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.ValueProvider = valueProvider;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt;     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt;      &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; IEnumerable&amp;lt;&lt;span style="color: #0000ff"&gt;object&lt;/span&gt;&amp;gt; GetParameterValues(ActionDescriptor actionDescriptor)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum10"&gt;  10:&lt;/span&gt;     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum11"&gt;  11:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;foreach&lt;/span&gt; (ParameterDescriptor parameterDescriptor &lt;span style="color: #0000ff"&gt;in&lt;/span&gt; actionDescriptor.GetParameters())&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum12"&gt;  12:&lt;/span&gt;         {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum13"&gt;  13:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; prefix = parameterDescriptor.BindingInfo.Prefix ?? parameterDescriptor.ParameterName;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum14"&gt;  14:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;yield&lt;/span&gt; &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; GetParameterValue(parameterDescriptor, prefix);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum15"&gt;  15:&lt;/span&gt;         }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum16"&gt;  16:&lt;/span&gt;     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum17"&gt;  17:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum18"&gt;  18:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;object&lt;/span&gt; GetParameterValue(ParameterDescriptor parameterDescriptor, &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; prefix)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum19"&gt;  19:&lt;/span&gt;     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum20"&gt;  20:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;object&lt;/span&gt; parameterValue = BindModel(parameterDescriptor.ParameterType, prefix);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum21"&gt;  21:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;null&lt;/span&gt; == parameterValue &amp;amp;&amp;amp; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt;.IsNullOrEmpty(parameterDescriptor.BindingInfo.Prefix))&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum22"&gt;  22:&lt;/span&gt;         {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum23"&gt;  23:&lt;/span&gt;             parameterValue = BindModel( parameterDescriptor.ParameterType, &lt;span style="color: #006080"&gt;&amp;quot;&amp;quot;&lt;/span&gt;);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum24"&gt;  24:&lt;/span&gt;         }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum25"&gt;  25:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; parameterValue ?? parameterDescriptor.DefaultValue;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum26"&gt;  26:&lt;/span&gt;      }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum27"&gt;  27:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum28"&gt;  28:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;object&lt;/span&gt; BindModel(Type parameterType, &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; prefix)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum29"&gt;  29:&lt;/span&gt;     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum30"&gt;  30:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (!&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.ValueProvider.ContainsPrefix(prefix))&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum31"&gt;  31:&lt;/span&gt;         {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum32"&gt;  32:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum33"&gt;  33:&lt;/span&gt;         }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum34"&gt;  34:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.ValueProvider.GetValue(prefix).ConvertTo(parameterType);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum35"&gt;  35:&lt;/span&gt;     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum36"&gt;  36:&lt;/span&gt; }&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;方法GetParameterValues根据指定的用于描述Action方法的ActionDescriptor获取最终执行该方法的所有参数值。在该方法中，我们通过调用ActionDescriptor的GetParameters方法得到用于描述其参数的所有ParameterDescriptor对象，并将每一个ParameterDescriptor作为参数调用GetParameterValue方法得到具体某个参数的值。GetParameterValue除了接受一个类型为ParameterDescriptor的参数外，还接受一个用于表示前缀的字符串参数。如果通过ParameterDescriptor的BindingInfo属性表示的ParameterBindingInfo对象具有前缀，则采用该前缀；否则采用参数名称作为前缀。&lt;/p&gt;&lt;p&gt;对于GetParameterValue方法来说，它又通过调用另一个将参数类型作为参数的BindModel方法来提供具体的参数值，BindModel方法同样接受一个表示前缀的字符串作为其第二个参数。GetParameterValue最初将通过ParameterDescriptor获取到的参数值和前缀作为参数调用BindModel方法，如果返回值为Null并且参数并没有显示执行前缀，会传入一个空字符串作为前缀再一次调用BindModel方法，这实际上模拟了之前提到过的去除前缀的后备Model绑定机制（针对于ModelBindingContext的FallbackToEmptyPrefix属性）。如果最终得到的对象不为Null，则将其作为参数值返回；否则返回参数的默认值。&lt;/p&gt;&lt;p&gt;BindModel方法的逻辑非常简单。先将传入的前缀作为参数调用ValueProvider的ContainsPrefix方法判断当前的ValueProvider保持的数据是否具有该前缀。如果返回之为False，直接返回Null，否则以此前缀作为Key调用GetValue方法得到一个ValueProviderResult调用，并最终调用ConvertTo方法转换为参数类型并返回。&lt;/p&gt;&lt;p&gt;为了验证我们自定义的DefaultModelBinder能够真正地用于针对简单参数类型的Model绑定没我们将它应用到一个具体的ASP.NET MVC应用中。在通过Visual Studio的ASP.NET MVC项目模板创建的空Web应用中，我们创建了如下一个默认的HomeController。HomeController具有一个ModelBinder属性，其类型正是我们自定义的DefaultModelBinder，该属性通过方法GetValueProvider提供。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; HomeController : Controller&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; DefaultModelBinder ModelBinder { get; &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; set; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; HomeController()&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.ModelBinder = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; DefaultModelBinder(GetValueProvider());&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt;     }       &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; InvokeAction(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; actionName)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt;     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum10"&gt;  10:&lt;/span&gt;         ControllerDescriptor controllerDescriptor = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; ReflectedControllerDescriptor(&lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(HomeController));&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum11"&gt;  11:&lt;/span&gt;         ReflectedActionDescriptor actionDescriptor = (ReflectedActionDescriptor)controllerDescriptor&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum12"&gt;  12:&lt;/span&gt;             .FindAction(ControllerContext, actionName);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum13"&gt;  13:&lt;/span&gt;         actionDescriptor.MethodInfo.Invoke(&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;,&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.ModelBinder.GetParameterValues(actionDescriptor).ToArray());&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum14"&gt;  14:&lt;/span&gt;     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum15"&gt;  15:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; Index()&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum16"&gt;  16:&lt;/span&gt;     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum17"&gt;  17:&lt;/span&gt;         InvokeAction(&lt;span style="color: #006080"&gt;&amp;quot;Action&amp;quot;&lt;/span&gt;);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum18"&gt;  18:&lt;/span&gt;     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum19"&gt;  19:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum20"&gt;  20:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; IValueProvider GetValueProvider()&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum21"&gt;  21:&lt;/span&gt;     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum22"&gt;  22:&lt;/span&gt;         NameValueCollection requestData = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; NameValueCollection();&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum23"&gt;  23:&lt;/span&gt;         requestData.Add(&lt;span style="color: #006080"&gt;&amp;quot;foo&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;abc&amp;quot;&lt;/span&gt;);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum24"&gt;  24:&lt;/span&gt;         requestData.Add(&lt;span style="color: #006080"&gt;&amp;quot;bar&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;123&amp;quot;&lt;/span&gt;);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum25"&gt;  25:&lt;/span&gt;         requestData.Add(&lt;span style="color: #006080"&gt;&amp;quot;baz&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;123.45&amp;quot;&lt;/span&gt;);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum26"&gt;  26:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; NameValueCollectionValueProvider(requestData, CultureInfo.InvariantCulture);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum27"&gt;  27:&lt;/span&gt;     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum28"&gt;  28:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; Action(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; foo, [Bind(Prefix=&lt;span style="color: #006080"&gt;&amp;quot;baz&amp;quot;&lt;/span&gt;)]&lt;span style="color: #0000ff"&gt;double&lt;/span&gt; bar)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum29"&gt;  29:&lt;/span&gt;     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum30"&gt;  30:&lt;/span&gt;         Response.Write(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;.Format(&lt;span style="color: #006080"&gt;&amp;quot;{0}: {1}&amp;lt;br/&amp;gt;&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;foo&amp;quot;&lt;/span&gt;, foo));&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum31"&gt;  31:&lt;/span&gt;         Response.Write(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;.Format(&lt;span style="color: #006080"&gt;&amp;quot;{0}: {1}&amp;lt;br/&amp;gt;&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;bar&amp;quot;&lt;/span&gt;, bar));&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum32"&gt;  32:&lt;/span&gt;     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum33"&gt;  33:&lt;/span&gt; }&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;InvokeAction方法用于执行指定的Action方法。在该方法中我们先根据当前Controller的类型创建一个ControllerDescriptor对象，并通过调其FindAction方法得到用于描述指定Action方法的ActionDescriptor对象。通过之前的介绍我们知道这是一个ReflectedActionDescriptor对象，所以我们将其转化成ReflectedActionDescriptor类型得到Action方法对应的MethodInfo对象。最后调用DefaultModelBinder的GetParameterValues方法得到目标Action方法所有的参数，将其传入MethodInfo的Invoke方法以反射的形式对指定的Action方法进行执行。&lt;/p&gt;&lt;p&gt;默认的Action方法Index中我们通过执行InvokeAction方法来执行定义在HomeController的Action方法。通过上面的代码片断可以看出，该方法的两个参数foo和bar均为简单类型（string和double），在参数bar上还应用了BindAttribute并指定了相应的前缀（“baz”）。在该Action方法中，我们将两个参数值呈现出来。&lt;/p&gt;&lt;p&gt;而在用于提供ValueProvider的GetValueProvider方法返回的是一个NameValueCollectionValueProvider对象。作为数据源的NameValueCollection对象包含三个名称为foo、bar和baz的数据（abc、123、123.45），我们可以将它们看成是Post的标单输入元素。&lt;/p&gt;&lt;p&gt;当我们运行该程序的时候会在浏览器中得到如下的输出结果。我们可以看到目标Action方法的两个参数值均通过我们自定义的DefaultModelBinder得到了有效的绑定。而实际上参数值的提供最终是通过ValueProvider实现的，它在默认的情况下会根据参数名称进行匹配（foo参数），如果参数应用BindAttribute并显式指定了前缀，则会按照这个前缀进行匹配（bar参数）。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; foo: abc&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; bar: 123.45&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;&lt;strong&gt;&lt;font size="4"&gt;&lt;font style="font-weight: bold"&gt;二、复杂类型&lt;/font&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;对于简单类型的参数来说，由于支持与字符串类型之间的转换，相应ValueProvider可以直接从数据源中提取相应的数据并直接转换成参数类型。所以针对简单类型的Model绑定是一步到位的过程，但是针对复杂类型的Model绑定就没有这么简单了。复杂对象可以表示为一个树形层次化结构，其对象本身和属性代表相应的节点，叶子节点代表简单数据类型属性。而ValueProvider采用的数据源是一个扁平的数据结构，它通过基于属性名称前缀的Key实现与这个对象树中对应叶子节点的映射。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; Contact&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; Name { get; set; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; PhoneNo { get; set; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; EmailAddress { get; set; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; Address Address { get; set; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; Address&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt; {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum10"&gt;  10:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; Province { get; set; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum11"&gt;  11:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; City { get; set; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum12"&gt;  12:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; District { get; set; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum13"&gt;  13:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; Street { get; set; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum14"&gt;  14:&lt;/span&gt; }&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;以上面定于得这个Contact类型为例，它具有三个简单类型的属性（Name、PhoneNo和EmailAddress）和复杂类型Address的属性；而Address属性具有四个简单类型的属性。一个Contact对象的数据结构可以通过如下图所示的树来表示，这个树种的所有叶子节点均为简单类型。如果我们需要通过一个ValueProvider来构建一个完整的Contact对象，它必须能够提供所有所有叶子节点的数值，而ValueProvider通过基于属性名称前缀的Key实现与对应的叶子节点的映射。&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/artech/201205/201205230819344013.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/artech/201205/201205230819347884.png" width="409" height="296" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;实际上当我们调用HtmlHelper&amp;lt;TModel&amp;gt;的模板方法EditorFor/EditorForModel的时候就是按照这样的匹配方式对标单元素进行命名的。假设在将Contact作为Model类型的强类型View中，我们通过调用HtmlHelper&amp;lt;TModel&amp;gt;的扩展方法EditorFor将Model对象的所有信息以编辑的模式呈现出来。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; @model Contact&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; @Html.EditorFor(m =&amp;gt; m.Name)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt; @Html.EditorFor(m =&amp;gt; m.PhoneNo)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt; @Html.EditorFor(m =&amp;gt; m.EmailAddress)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt; @Html.EditorFor(m =&amp;gt; m.Address.Province)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt; @Html.EditorFor(m =&amp;gt; m.Address.City)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt; @Html.EditorFor(m =&amp;gt; m.Address.District)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt; @Html.EditorFor(m =&amp;gt; m.Address.Street)&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;下面的代码片断代表了作为Model对象的Contact在最终呈现出来的View中代表的HTML，我们可以清楚地看到这些&amp;lt;input&amp;gt;表单元素完全是根据属性名称和类型层次结构进行命名的。随便提一下，对于基于提交表单的Model绑定来说，作为匹配的是表单元素的name属性而非id属性，所以这里的命名指的是name属性而非id属性。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;input&lt;/span&gt; &lt;span style="color: #ff0000"&gt;id&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;Name&amp;quot;&lt;/span&gt; &lt;span style="color: #ff0000"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;Name&amp;quot;&lt;/span&gt; &lt;span style="color: #ff0000"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;text&amp;quot;&lt;/span&gt; ... &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;input&lt;/span&gt; &lt;span style="color: #ff0000"&gt;id&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;PhoneNo&amp;quot;&lt;/span&gt; &lt;span style="color: #ff0000"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;PhoneNo&amp;quot;&lt;/span&gt; &lt;span style="color: #ff0000"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;text&amp;quot;&lt;/span&gt; ... &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;input&lt;/span&gt; &lt;span style="color: #ff0000"&gt;id&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;EmailAddress&amp;quot;&lt;/span&gt; &lt;span style="color: #ff0000"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;EmailAddress&amp;quot;&lt;/span&gt; &lt;span style="color: #ff0000"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;text&amp;quot;&lt;/span&gt; ... &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;input&lt;/span&gt; &lt;span style="color: #ff0000"&gt;id&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;Address_Province&amp;quot;&lt;/span&gt; &lt;span style="color: #ff0000"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;Address.Province&amp;quot;&lt;/span&gt; &lt;span style="color: #ff0000"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;text&amp;quot;&lt;/span&gt; ... &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;input&lt;/span&gt; &lt;span style="color: #ff0000"&gt;id&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;Address_City&amp;quot;&lt;/span&gt; &lt;span style="color: #ff0000"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;Address.City&amp;quot;&lt;/span&gt; &lt;span style="color: #ff0000"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;text&amp;quot;&lt;/span&gt; ... &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;input&lt;/span&gt; &lt;span style="color: #ff0000"&gt;id&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;Address_District&amp;quot;&lt;/span&gt; &lt;span style="color: #ff0000"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;Address.District&amp;quot;&lt;/span&gt; &lt;span style="color: #ff0000"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;text&amp;quot;&lt;/span&gt; ... &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;input&lt;/span&gt; &lt;span style="color: #ff0000"&gt;id&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;Address_Street&amp;quot;&lt;/span&gt; &lt;span style="color: #ff0000"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;Address.Street&amp;quot;&lt;/span&gt; &lt;span style="color: #ff0000"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;text&amp;quot;&lt;/span&gt;... &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;对于用于模拟默认Model绑定机制的自定义DefaultModelBinder来说，我们仅仅提供了针对简单类型的绑定，现在我们对其进行完善是之可以提供对复杂类型的Model绑定。如下面的代码片断所示，在BindModel方法中我们创建了一个基于参数类型的ModelMetadata对象，并根据其IsComplexType属性判断参数类型是否为复杂类型。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; DefaultModelBinder&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color: #008000"&gt;//其他成员&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;object&lt;/span&gt; BindModel(Type parameterType, &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; prefix)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (!&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.ValueProvider.ContainsPrefix(prefix))&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt;         {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt;         }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum10"&gt;  10:&lt;/span&gt;         ModelMetadata modelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() =&amp;gt; &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;, parameterType);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum11"&gt;  11:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (!modelMetadata.IsComplexType)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum12"&gt;  12:&lt;/span&gt;         {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum13"&gt;  13:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.ValueProvider.GetValue(prefix).ConvertTo(parameterType);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum14"&gt;  14:&lt;/span&gt;         }            &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum15"&gt;  15:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;object&lt;/span&gt; model = CreateModel(parameterType);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum16"&gt;  16:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;foreach&lt;/span&gt; (PropertyDescriptor property &lt;span style="color: #0000ff"&gt;in&lt;/span&gt; TypeDescriptor.GetProperties(parameterType))&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum17"&gt;  17:&lt;/span&gt;         {                &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum18"&gt;  18:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; key = &lt;span style="color: #0000ff"&gt;string&lt;/span&gt;.IsNullOrEmpty(prefix) ? property.Name : prefix + &lt;span style="color: #006080"&gt;&amp;quot;.&amp;quot;&lt;/span&gt; + property.Name;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum19"&gt;  19:&lt;/span&gt;             property.SetValue(model, BindModel(property.PropertyType, key));&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum20"&gt;  20:&lt;/span&gt;         }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum21"&gt;  21:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; model;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum22"&gt;  22:&lt;/span&gt;     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum23"&gt;  23:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;object&lt;/span&gt; CreateModel(Type modelType)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum24"&gt;  24:&lt;/span&gt;     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum25"&gt;  25:&lt;/span&gt;         Type type = modelType;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum26"&gt;  26:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (modelType.IsGenericType)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum27"&gt;  27:&lt;/span&gt;         {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum28"&gt;  28:&lt;/span&gt;             Type genericTypeDefinition = modelType.GetGenericTypeDefinition();&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum29"&gt;  29:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (genericTypeDefinition == &lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(IDictionary&amp;lt;,&amp;gt;))&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum30"&gt;  30:&lt;/span&gt;             {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum31"&gt;  31:&lt;/span&gt;                 type = &lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(Dictionary&amp;lt;,&amp;gt;).MakeGenericType(modelType.GetGenericArguments());&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum32"&gt;  32:&lt;/span&gt;             }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum33"&gt;  33:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;else&lt;/span&gt; &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (((genericTypeDefinition == &lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(IEnumerable&amp;lt;&amp;gt;)) || (genericTypeDefinition == &lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(ICollection&amp;lt;&amp;gt;))) ||(genericTypeDefinition == &lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(IList&amp;lt;&amp;gt;)))&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum34"&gt;  34:&lt;/span&gt;             {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum35"&gt;  35:&lt;/span&gt;                 type = &lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(List&amp;lt;&amp;gt;).MakeGenericType(&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum36"&gt;  36:&lt;/span&gt;                 modelType.GetGenericArguments());&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum37"&gt;  37:&lt;/span&gt;             }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum38"&gt;  38:&lt;/span&gt;         }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum39"&gt;  39:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; Activator.CreateInstance(type);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum40"&gt;  40:&lt;/span&gt;     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum41"&gt;  41:&lt;/span&gt; }&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;如果参数为复杂类型，则通过调用CreateModel方法以反射的方式创建Model对象。CreateModel方法会被用于后面我们会介绍的基于集合和字典的Model绑定，所以我们这里还针对泛型的IDictionary&amp;lt;,&amp;gt;、IEnumerable&amp;lt;&amp;gt;、ICollection&amp;lt;&amp;gt;和IList&amp;lt;&amp;gt;类型作了相应地处理。具体来说，如果参数类型为IDictionary&amp;lt;,&amp;gt;，则创建一个Dictionary&amp;lt;,&amp;gt;对象，而对后三者则创建一个List&amp;lt;&amp;gt;对象，具体的泛型参数根据参数类型获取。对于一般的类型，我们直接通过Activator的CreateInstance方法根据参数类型创建相应的Model对象。&lt;/p&gt;&lt;p&gt;通过CreateModel方法创建的是针对参数类型的“空”对象，我们需要通过Model绑定对它的相关属性进行初始化。在BindModel方法中，我们遍历参数类型的所有属性，并在现有前缀的基础上加上“.{属性名称}”（如果当前前缀为空，则直接采用属性名称）作为绑定对应属性的前缀递归地调用BindModel方法得到属性值。我们最终通过反射的方式将得到值对属性进行赋值。&lt;/p&gt;&lt;p&gt;现在我们采用我们完善后的DefaultModelBinder来进行针对复杂类型的Model绑定。如下面的代码片断所示，我们对HomeController的Action方法进行了相应的修改使之具有两个Contact类型的参数foo和bar。在Action方法中，我们将这两个参数代表的Contact对象的相关信息呈现出来。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; HomeController : Controller&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; DefaultModelBinder ModelBinder { get; &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; set; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; HomeController()&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.ModelBinder = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; DefaultModelBinder(GetValueProvider());&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt;     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; IValueProvider GetValueProvider()&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum10"&gt;  10:&lt;/span&gt;     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum11"&gt;  11:&lt;/span&gt;         NameValueCollection requestData = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; NameValueCollection();&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum12"&gt;  12:&lt;/span&gt;         requestData.Add(&lt;span style="color: #006080"&gt;&amp;quot;Name&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;张三&amp;quot;&lt;/span&gt;);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum13"&gt;  13:&lt;/span&gt;         requestData.Add(&lt;span style="color: #006080"&gt;&amp;quot;PhoneNo&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;123456789&amp;quot;&lt;/span&gt;);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum14"&gt;  14:&lt;/span&gt;         requestData.Add(&lt;span style="color: #006080"&gt;&amp;quot;EmailAddress&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;zhangsan@gmail.com&amp;quot;&lt;/span&gt;);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum15"&gt;  15:&lt;/span&gt;         requestData.Add(&lt;span style="color: #006080"&gt;&amp;quot;Address.Province&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;江苏&amp;quot;&lt;/span&gt;);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum16"&gt;  16:&lt;/span&gt;         requestData.Add(&lt;span style="color: #006080"&gt;&amp;quot;Address.City&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;苏州&amp;quot;&lt;/span&gt;);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum17"&gt;  17:&lt;/span&gt;         requestData.Add(&lt;span style="color: #006080"&gt;&amp;quot;Address.District&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;工业园区&amp;quot;&lt;/span&gt;);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum18"&gt;  18:&lt;/span&gt;         requestData.Add(&lt;span style="color: #006080"&gt;&amp;quot;Address.Street&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;星湖街328号&amp;quot;&lt;/span&gt;);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum19"&gt;  19:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; NameValueCollectionValueProvider(requestData, CultureInfo.InvariantCulture);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum20"&gt;  20:&lt;/span&gt;     }    &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum21"&gt;  21:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum22"&gt;  22:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; Index()&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum23"&gt;  23:&lt;/span&gt;     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum24"&gt;  24:&lt;/span&gt;         InvokeAction(&lt;span style="color: #006080"&gt;&amp;quot;Action&amp;quot;&lt;/span&gt;);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum25"&gt;  25:&lt;/span&gt;     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum26"&gt;  26:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum27"&gt;  27:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; Action(Contact foo, Contact bar)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum28"&gt;  28:&lt;/span&gt;     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum29"&gt;  29:&lt;/span&gt;         Response.Write(&lt;span style="color: #006080"&gt;&amp;quot;Foo&amp;lt;br/&amp;gt;&amp;quot;&lt;/span&gt;);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum30"&gt;  30:&lt;/span&gt;         Response.Write(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;.Format(&lt;span style="color: #006080"&gt;&amp;quot;{0}: {1}&amp;lt;br/&amp;gt;&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;Name&amp;quot;&lt;/span&gt;, foo.Name));&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum31"&gt;  31:&lt;/span&gt;         Response.Write(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;.Format(&lt;span style="color: #006080"&gt;&amp;quot;{0}: {1}&amp;lt;br/&amp;gt;&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;PhoneNo&amp;quot;&lt;/span&gt;, foo.PhoneNo));&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum32"&gt;  32:&lt;/span&gt;         Response.Write(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;.Format(&lt;span style="color: #006080"&gt;&amp;quot;{0}: {1}&amp;lt;br/&amp;gt;&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;EmailAddress&amp;quot;&lt;/span&gt;, foo.EmailAddress));&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum33"&gt;  33:&lt;/span&gt;         Response.Write(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;.Format(&lt;span style="color: #006080"&gt;&amp;quot;{0}: {1} {2} {3} {4}&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;Address&amp;quot;&lt;/span&gt;, &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum34"&gt;  34:&lt;/span&gt;            foo.Address.Province, foo.Address.City, foo.Address.District, &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum35"&gt;  35:&lt;/span&gt;            foo.Address.Street));&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum36"&gt;  36:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum37"&gt;  37:&lt;/span&gt;         Response.Write(&lt;span style="color: #006080"&gt;&amp;quot;Bar&amp;lt;br/&amp;gt;&amp;quot;&lt;/span&gt;);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum38"&gt;  38:&lt;/span&gt;         Response.Write(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;.Format(&lt;span style="color: #006080"&gt;&amp;quot;{0}: {1}&amp;lt;br/&amp;gt;&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;Name&amp;quot;&lt;/span&gt;, bar.Name));&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum39"&gt;  39:&lt;/span&gt;         Response.Write(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;.Format(&lt;span style="color: #006080"&gt;&amp;quot;{0}: {1}&amp;lt;br/&amp;gt;&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;PhoneNo&amp;quot;&lt;/span&gt;, bar.PhoneNo));&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum40"&gt;  40:&lt;/span&gt;         Response.Write(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;.Format(&lt;span style="color: #006080"&gt;&amp;quot;{0}: {1}&amp;lt;br/&amp;gt;&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;EmailAddress&amp;quot;&lt;/span&gt;, bar.EmailAddress));&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum41"&gt;  41:&lt;/span&gt;         Response.Write(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;.Format(&lt;span style="color: #006080"&gt;&amp;quot;{0}: {1} {2} {3} {4}&amp;lt;br/&amp;gt;&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;Address&amp;quot;&lt;/span&gt;, &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum42"&gt;  42:&lt;/span&gt;             bar.Address.Province, bar.Address.City, bar.Address.District, &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum43"&gt;  43:&lt;/span&gt;             bar.Address.Street)); &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum44"&gt;  44:&lt;/span&gt;     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum45"&gt;  45:&lt;/span&gt; }&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;通过GetValueProvider方法提供的依然是一个NameValueCollectionValueProvider对象，我们将一个Contact对象包含的信息包含在它对应的NameValueCollection对象中。对于添加到NameValueCollection中的针对Contact对象的某个属性的数据条目，我们按照上面介绍的匹配规则对其命名。运行我们的实例程序，我们会在浏览器中得到如下所示的输出结果，我们从中可以看到Action方法的两个参数foo和bar通过我们自定义的DefaultModelBinder进行了正确地绑定，并且它们具有相同的值。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; Foo&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; Name: 张三&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt; PhoneNo: 123456789&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt; EmailAddress: zhangsan@gmail.com&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt; Address: 江苏 苏州 工业园区 星湖街328号&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt; Bar&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt; Name: 张三&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt; PhoneNo: 123456789&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum10"&gt;  10:&lt;/span&gt; EmailAddress: zhangsan@gmail.com&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum11"&gt;  11:&lt;/span&gt; Address: 江苏 苏州 工业园区 星湖街328号&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;之所以同一个Action方法中两个相同类型的参数会绑定相同的数据，使缘于之前介绍的去除前缀的后备Model绑定机制。由于请求数据中并不包含针对某个参数的前缀，所以在针对参数名称作为前缀的Model绑定失败的情况下，后备Model绑定会前缀为空字符串的情况下再次进行。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; HomeController : Controller&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color: #008000"&gt;//其他成员&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; IValueProvider GetValueProvider()&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;         NameValueCollection requestData = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; NameValueCollection();&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt;         requestData.Add(&lt;span style="color: #006080"&gt;&amp;quot;foo.Name&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;Foo&amp;quot;&lt;/span&gt;);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt;         requestData.Add(&lt;span style="color: #006080"&gt;&amp;quot;foo.PhoneNo&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;123456789&amp;quot;&lt;/span&gt;);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt;         requestData.Add(&lt;span style="color: #006080"&gt;&amp;quot;foo.EmailAddress&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;Foo@gmail.com&amp;quot;&lt;/span&gt;);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum10"&gt;  10:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum11"&gt;  11:&lt;/span&gt;         requestData.Add(&lt;span style="color: #006080"&gt;&amp;quot;bar.Name&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;Bar&amp;quot;&lt;/span&gt;);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum12"&gt;  12:&lt;/span&gt;         requestData.Add(&lt;span style="color: #006080"&gt;&amp;quot;bar.PhoneNo&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;987654321&amp;quot;&lt;/span&gt;);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum13"&gt;  13:&lt;/span&gt;         requestData.Add(&lt;span style="color: #006080"&gt;&amp;quot;bar.EmailAddress&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;Bar@gmail.com&amp;quot;&lt;/span&gt;);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum14"&gt;  14:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; NameValueCollectionValueProvider(requestData, CultureInfo.InvariantCulture);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum15"&gt;  15:&lt;/span&gt;     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum16"&gt;  16:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum17"&gt;  17:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; Action(Contact foo, Contact bar)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum18"&gt;  18:&lt;/span&gt;     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum19"&gt;  19:&lt;/span&gt;         Response.Write(&lt;span style="color: #006080"&gt;&amp;quot;Foo&amp;lt;br/&amp;gt;&amp;quot;&lt;/span&gt;);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum20"&gt;  20:&lt;/span&gt;         Response.Write(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;.Format(&lt;span style="color: #006080"&gt;&amp;quot;{0}: {1}&amp;lt;br/&amp;gt;&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;Name&amp;quot;&lt;/span&gt;, foo.Name));&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum21"&gt;  21:&lt;/span&gt;         Response.Write(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;.Format(&lt;span style="color: #006080"&gt;&amp;quot;{0}: {1}&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;PhoneNo&amp;quot;&lt;/span&gt;, foo.PhoneNo));&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum22"&gt;  22:&lt;/span&gt;         Response.Write(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;.Format(&lt;span style="color: #006080"&gt;&amp;quot;{0}: {1}&amp;lt;br/&amp;gt;&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;EmailAddress&amp;quot;&lt;/span&gt;, foo.EmailAddress));&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum23"&gt;  23:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum24"&gt;  24:&lt;/span&gt;         Response.Write(&lt;span style="color: #006080"&gt;&amp;quot;Bar&amp;lt;br/&amp;gt;&amp;quot;&lt;/span&gt;);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum25"&gt;  25:&lt;/span&gt;         Response.Write(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;.Format(&lt;span style="color: #006080"&gt;&amp;quot;{0}: {1}&amp;lt;br/&amp;gt;&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;Name&amp;quot;&lt;/span&gt;, bar.Name));&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum26"&gt;  26:&lt;/span&gt;         Response.Write(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;.Format(&lt;span style="color: #006080"&gt;&amp;quot;{0}: {1}&amp;lt;br/&amp;gt;&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;PhoneNo&amp;quot;&lt;/span&gt;, bar.PhoneNo));&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum27"&gt;  27:&lt;/span&gt;         Response.Write(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;.Format(&lt;span style="color: #006080"&gt;&amp;quot;{0}: {1}&amp;lt;br/&amp;gt;&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;EmailAddress&amp;quot;&lt;/span&gt;,   bar.EmailAddress));&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum28"&gt;  28:&lt;/span&gt;     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum29"&gt;  29:&lt;/span&gt; }&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;在如上所示的代码中，我们为NameValueCollectionValueProvider设置了基于“foo”和“bar”的前缀的两套数据，目的在为Action方法的foo和bar参数提供不同的数据。运行我们的程序后会在浏览器上得到如下所示的输出结果，可以看出Action方法的两个参数被绑定了不同的值。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; Foo&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; Name: Foo&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt; PhoneNo: 123456789&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt; EmailAddress: Foo@gmail.com&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt; Bar&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt; Name: Bar&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt; PhoneNo: 987654321&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt; EmailAddress: &lt;a href="mailto:Bar@gmail.com"&gt;Bar@gmail.com&lt;/a&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;&amp;#160;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/artech/archive/2012/05/23/default-model-binding-01.html"&gt;通过实例模拟ASP.NET MVC的Model绑定的机制[上篇]&lt;/a&gt;   &lt;br /&gt;&lt;a href="http://www.cnblogs.com/artech/archive/2012/05/24/default-model-binding-02.html"&gt;通过实例模拟ASP.NET MVC的Model绑定的机制[下篇]&lt;/a&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/artech/aggbug/2514174.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/artech/archive/2012/05/23/default-model-binding-01.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/artech/archive/2012/05/21/model-binder-provision.html</id><title type="text">ModelBinder&amp;mdash;&amp;mdash;ASP.NET MVC Model绑定的核心</title><summary type="text">Model的绑定体现在从当前请求提取相应的数据绑定到目标Action方法的参数。通过前面的介绍我们知道Action方法的参数通过ParameterDescriptor来描述，ParameterDescriptor的BindingInfo属性表示的ParameterBindingInfo对象具有一个名为ModelBinder的组件用于完成针对当前参数的Model绑定。ModelBinder可以看成是整个Model绑定系统的核心，我们来认识这个重要的组件以及相关的提供机制。</summary><published>2012-05-21T00:12:00Z</published><updated>2012-05-21T00:12:00Z</updated><author><name>Artech</name><uri>http://www.cnblogs.com/artech/</uri></author><link rel="alternate" href="http://www.cnblogs.com/artech/archive/2012/05/21/model-binder-provision.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/artech/archive/2012/05/21/model-binder-provision.html"/><content type="html">&lt;p&gt;Model的绑定体现在从当前请求提取相应的数据绑定到目标Action方法的参数。通过前面的介绍我们知道Action方法的参数通过ParameterDescriptor来描述，ParameterDescriptor的BindingInfo属性表示的ParameterBindingInfo对象具有一个名为ModelBinder的组件用于完成针对当前参数的Model绑定。ModelBinder可以看成是整个Model绑定系统的核心，我们先来认识这个重要的组件。[本文已经同步到《&lt;a href="http://www.cnblogs.com/artech/archive/2012/04/10/how-mvc-works.html"&gt;How ASP.NET MVC Works?&lt;/a&gt;》中]&lt;/p&gt;  &lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;   &lt;p&gt;目录      &lt;br /&gt;一、 ModelBinder       &lt;br /&gt;二、CustomModelBinderAttribute与ModelBinderAttribute       &lt;br /&gt;三、ModelBinders       &lt;br /&gt;四、ModelBinderProvider &lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;strong&gt;&lt;font size="4"&gt;&lt;font style="font-weight: bold"&gt;一、 ModelBinder&lt;/font&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;用于进行Model绑定的ModelBinder对象实现了接口&lt;a title="IModelBinder Interface" href="http://msdn2.microsoft.com/dd505004.aspx"&gt;IModelBinder&lt;/a&gt;。如下面的代码片断所示，IModelBinder接口具有唯一的BindModel方法用于实现针对某个参数的绑定操作，该方法的返回值表示的就是最终作为参数值的对象。&lt;/p&gt;  &lt;div id="codeSnippetWrapper"&gt;   &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;     &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;interface&lt;/span&gt; IModelBinder&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;object&lt;/span&gt; BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt; }&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;IModelBinder的BindModel方法接受两个参数，一个是表示当前的Controller上下文，另一个是表示针对当前Model绑定的上下文，通过类型&lt;a title="ModelBindingContext Class" href="http://msdn2.microsoft.com/hh195362.aspx"&gt;ModelBindingContext&lt;/a&gt;表示。在Controller初始化的时候，Controller上下文已经被创建出来，所以我们只要能够针对当前的Model绑定创建相应的ModelBindingContext，我们就能使用基于某个参数的ModelBinder得到对应的参数值。关于ModelBindingContext的创建我们会在后续部分进行的单独介绍，我们先来介绍一下ModelBinder的提供机制。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;font size="4"&gt;&lt;font style="font-weight: bold"&gt;二、CustomModelBinderAttribute与ModelBinderAttribute&lt;/font&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;如果针对某个&lt;font color="#ff0000"&gt;参数&lt;/font&gt;的ParameterDescriptor具有相应的ModelBinder，那么它会被优先选择用于针对该参数的Model绑定，那么ParameterDescriptor的ModelBinder是如何来提供的呢？这是实际上设置一个具有如下定义的&lt;a title="CustomModelBinderAttribute Class" href="http://msdn2.microsoft.com/dd492121.aspx"&gt;CustomModelBinderAttribute&lt;/a&gt;特性。抽象类CustomModelBinderAttribute定义了唯一的抽象方法GetBinder用于获取相应的ModelBinder对象。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Interface | AttributeTargets.Enum | AttributeTargets.Struct &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt;     | AttributeTargets.Class, AllowMultiple=&lt;span style="color: #0000ff"&gt;false&lt;/span&gt;, Inherited=&lt;span style="color: #0000ff"&gt;false&lt;/span&gt;)]&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;abstract&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; CustomModelBinderAttribute : Attribute&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt; {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;abstract&lt;/span&gt; IModelBinder GetBinder();&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt; }&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;在ASP.NET MVC应用编程接口中，CustomModelBinderAttribute具有一个具有如下定义的唯一继承类型&lt;a title="ModelBinderAttribute Class" href="http://msdn2.microsoft.com/dd492740.aspx"&gt;ModelBinderAttribute&lt;/a&gt;。我们可以通过应用ModelBinderAttribute特性动态地选择用于Model绑定的ModelBinder类型。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Interface | &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt;     AttributeTargets.Enum | AttributeTargets.Struct | AttributeTargets.Class, &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     AllowMultiple=&lt;span style="color: #0000ff"&gt;false&lt;/span&gt;, Inherited=&lt;span style="color: #0000ff"&gt;false&lt;/span&gt;)]&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;sealed&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; ModelBinderAttribute : CustomModelBinderAttribute&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt; {   &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; ModelBinderAttribute(Type binderType);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;override&lt;/span&gt; IModelBinder GetBinder();&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; Type BinderType { [CompilerGenerated] get;  }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum10"&gt;  10:&lt;/span&gt; }&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;从应用在ModelBinderAttribute类型上的AttributeUsageAttribute定义可以看出该特性不仅仅可以应用在参数上，也可以应用类型（接口、枚举、结构和类）上，这意味我们既可以将它应用在Action方法的某个参数上，也可以将它应用在某个参数的类型上。但是ParameterDescriptor只会解析应用在参数上的特性，所以应用在参数对象类型上的ModelBinderAttribute对它是无效的。&lt;/p&gt;&lt;p&gt;为了演示ModelBinderAttribute特性对ParameterDescriptor的影响，我们来进行一个简单的实例演示。在一个通过Visual Studio的ASP.NET MVC项目模板创建的空Web应用中定义了如下几个类型，其中FooModelBinder和BarModelBinder是显现了IModelBinder的自定义ModelBinder类型，而Foo、Bar和Baz是三个将被作为Action方法参数的数据类型，其中Bar上应用了ModelBinderAttribute特性并将ModelBinder类型设置为BarModelBinder。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; FooModelBinder : IModelBinder&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;object&lt;/span&gt; BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;throw&lt;/span&gt; &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; NotImplementedException();&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; BarModelBinder : IModelBinder&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt; {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum10"&gt;  10:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;object&lt;/span&gt; BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum11"&gt;  11:&lt;/span&gt;     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum12"&gt;  12:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;throw&lt;/span&gt; &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; NotImplementedException();&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum13"&gt;  13:&lt;/span&gt;     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum14"&gt;  14:&lt;/span&gt; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum15"&gt;  15:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum16"&gt;  16:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; Foo { }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum17"&gt;  17:&lt;/span&gt; [ModelBinder(&lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(BarModelBinder))]&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum18"&gt;  18:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; Bar { }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum19"&gt;  19:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; Baz { }&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;然后再创建的默认HomeController中定义如下两个Action方法。DoSomething方法具有三个参数，类型分别是Foo、Bar和Baz，在第一个参数上应用了ModelBinderAttribute特性并将ModelBinder类型设置为FooModelBinder。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; HomeController : Controller&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; Index()&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;         ControllerDescriptor controllerDescriptor = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; ReflectedControllerDescriptor(&lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(HomeController));&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;         ActionDescriptor actionDescriptor = controllerDescriptor.FindAction(ControllerContext, &lt;span style="color: #006080"&gt;&amp;quot;DoSomething&amp;quot;&lt;/span&gt;);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt;         IModelBinder foo = actionDescriptor.GetParameters().First(p =&amp;gt; p.ParameterName == &lt;span style="color: #006080"&gt;&amp;quot;foo&amp;quot;&lt;/span&gt;).BindingInfo.Binder;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt;         IModelBinder bar = actionDescriptor.GetParameters().First(p =&amp;gt; p.ParameterName == &lt;span style="color: #006080"&gt;&amp;quot;bar&amp;quot;&lt;/span&gt;).BindingInfo.Binder;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt;         IModelBinder baz = actionDescriptor.GetParameters().First(p =&amp;gt; p.ParameterName == &lt;span style="color: #006080"&gt;&amp;quot;baz&amp;quot;&lt;/span&gt;).BindingInfo.Binder;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum10"&gt;  10:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum11"&gt;  11:&lt;/span&gt;         Response.Write(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;.Format(&lt;span style="color: #006080"&gt;&amp;quot;foo: {0}&amp;lt;br/&amp;gt;&amp;quot;&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;null&lt;/span&gt; == foo? &lt;span style="color: #006080"&gt;&amp;quot;N/A&amp;quot;&lt;/span&gt;: foo.GetType().Name));&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum12"&gt;  12:&lt;/span&gt;         Response.Write(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;.Format(&lt;span style="color: #006080"&gt;&amp;quot;bar: {0}&amp;lt;br/&amp;gt;&amp;quot;&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;null&lt;/span&gt; == bar ? &lt;span style="color: #006080"&gt;&amp;quot;N/A&amp;quot;&lt;/span&gt; : bar.GetType().Name));&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum13"&gt;  13:&lt;/span&gt;         Response.Write(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;.Format(&lt;span style="color: #006080"&gt;&amp;quot;baz: {0}&amp;lt;br/&amp;gt;&amp;quot;&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;null&lt;/span&gt; == baz ? &lt;span style="color: #006080"&gt;&amp;quot;N/A&amp;quot;&lt;/span&gt; : baz.GetType().Name));&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum14"&gt;  14:&lt;/span&gt;     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum15"&gt;  15:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum16"&gt;  16:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; DoSomething([ModelBinder(&lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(FooModelBinder))]Foo foo,Bar bar, Bar baz)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum17"&gt;  17:&lt;/span&gt;     {}                &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum18"&gt;  18:&lt;/span&gt; }&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;在默认的Action方法Index中，我们针对HomeController类型的ReflectedControllerDescriptor对象并获取到用于描述Action方法DoSomething的ActionDescriptor对象。最后我们通过该ActionDescriptor对象得到用于描述其三个参数的ParameterDescriptor对象，并将其ModelBinder类西国内呈现出来。当我们运行该程序的时候，会在浏览器中产生如下的输出结果，可以看出&lt;font color="#ff0000"&gt;对于分别应用在参数和参数类型上的ModelBinderAttribute特性，只有前者会对ParameterDescriptor的ModelBinder的选择造成影响&lt;/font&gt;。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; foo: FooModelBinder&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; bar: N/A&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt; baz: N/A&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;&lt;strong&gt;&lt;font size="4"&gt;&lt;font style="font-weight: bold"&gt;三、ModelBinders&lt;/font&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;如果我们不曾通过ModelBinderAttribute特性为某个Action方法参数的ModelBinder类型进行显式定制，默认采用的Model是通过静态类型&lt;a title="ModelBinders Class" href="http://msdn2.microsoft.com/dd492987.aspx"&gt;ModelBinders&lt;/a&gt;来提供的。如下面的代码片断所示，ModelBinders具有一个静态只读属性Binders，表示当前注册ModelBinder列表，其类型为&lt;a title="ModelBinderDictionary Class" href="http://msdn2.microsoft.com/dd492249.aspx"&gt;ModelBinderDictionary&lt;/a&gt;。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; ModelBinders&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {   &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; ModelBinderDictionary Binders { get; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; ModelBinderDictionary : &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt;   IDictionary&amp;lt;Type, IModelBinder&amp;gt;, &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt;   ICollection&amp;lt;KeyValuePair&amp;lt;Type, IModelBinder&amp;gt;&amp;gt;, &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt;   IEnumerable&amp;lt;KeyValuePair&amp;lt;Type, IModelBinder&amp;gt;&amp;gt;, &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum10"&gt;  10:&lt;/span&gt;   IEnumerable&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum11"&gt;  11:&lt;/span&gt; {    &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum12"&gt;  12:&lt;/span&gt;     &lt;span style="color: #008000"&gt;//其他成员&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum13"&gt;  13:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; IModelBinder GetBinder(Type modelType);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum14"&gt;  14:&lt;/span&gt;    &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;virtual&lt;/span&gt; IModelBinder GetBinder(Type modelType, &lt;span style="color: #0000ff"&gt;bool&lt;/span&gt; fallbackToDefault);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum15"&gt;  15:&lt;/span&gt; }&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;ModelBinderDictionary是一个以&lt;font color="#ff0000"&gt;数据类型（Model类型）为Key，ModelBinder对象为Value&lt;/font&gt;的字典，即它定义了针对某种数据类型的ModelBinder。ModelBinderDictionary具有两个GetBinder方法重载用于获取针对某个数据类型的ModelBinder，布尔类型的参数fallbackToDefault表示在数据类型不存在的时候是否采用默认的ModelBinder，基于默认ModelBinder的后备机制会在第一个GetBinder方法重载中采用。在这里默认ModelBinder类型为&lt;a title="DefaultModelBinder Class" href="http://msdn2.microsoft.com/dd470193.aspx"&gt;DefaultModelBinder&lt;/a&gt;。&lt;/p&gt;&lt;p&gt;在为某个参数获取相应的ModelBinder的时候，如果对应的ParameterDescriptor的ModelBinder不存在，则通过ModelBinders的静态属性Binders表示获取到当前注册的ModelBinder列表的ModelBinderDictionary对象，并将参数类型作为参数调用其GetBinder方法获取相应ModelBinder对象。&lt;/p&gt;&lt;p&gt;我们根据ModelBinder的提供机制对上面演示的实例进行相应的修改。我们在HomeConroller中添加了一个CheckModelBinder方法，三个参数分别表示用于描述相应Action方法的ActionDescriptor对象、参数名称和类型。在该方法中我们先获取到用于描述制定参数的ParameterDescriptor对象，如果它具有相应的ModelBinder，则将具体的类型名称输出，否则输出通过ModelBinders获取的针对参数类型的ModelBinder类型。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; HomeController : Controller&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color: #008000"&gt;//其他成员&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; Index()&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;         ControllerDescriptor controllerDescriptor = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; ReflectedControllerDescriptor(&lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(HomeController));&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt;         ActionDescriptor actionDescriptor = controllerDescriptor.FindAction(ControllerContext, &lt;span style="color: #006080"&gt;&amp;quot;DoSomething&amp;quot;&lt;/span&gt;);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt;         CheckModelBinder(actionDescriptor, &lt;span style="color: #006080"&gt;&amp;quot;foo&amp;quot;&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(Foo));&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum10"&gt;  10:&lt;/span&gt;         CheckModelBinder(actionDescriptor, &lt;span style="color: #006080"&gt;&amp;quot;bar&amp;quot;&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(Bar));&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum11"&gt;  11:&lt;/span&gt;         CheckModelBinder(actionDescriptor, &lt;span style="color: #006080"&gt;&amp;quot;baz&amp;quot;&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(Baz));           &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum12"&gt;  12:&lt;/span&gt;     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum13"&gt;  13:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum14"&gt;  14:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; CheckModelBinder(ActionDescriptor actionDescriptor, &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; parameterName, Type modelType)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum15"&gt;  15:&lt;/span&gt;     { &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum16"&gt;  16:&lt;/span&gt;         ParameterDescriptor parameterDescriptor = actionDescriptor.GetParameters().First(p=&amp;gt;p.ParameterName == parameterName);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum17"&gt;  17:&lt;/span&gt;         IModelBinder modelBinder = parameterDescriptor.BindingInfo.Binder ?? ModelBinders.Binders.GetBinder(modelType);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum18"&gt;  18:&lt;/span&gt;         Response.Write(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;.Format(&lt;span style="color: #006080"&gt;&amp;quot;{0}: {1}&amp;lt;br/&amp;gt;&amp;quot;&lt;/span&gt;, parameterName, &lt;span style="color: #0000ff"&gt;null&lt;/span&gt; == modelBinder ? &lt;span style="color: #006080"&gt;&amp;quot;N/A&amp;quot;&lt;/span&gt; : modelBinder.GetType().Name));&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum19"&gt;  19:&lt;/span&gt;     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum20"&gt;  20:&lt;/span&gt; }&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;在Index方法中，我们调用CheckModelBinder方法将Action方法DoSomething的三个参数对应的ModelBinder类型呈现出来。当我们运行该程序的时候，在浏览器上会得到如下的输出结果，&lt;font color="#ff0000"&gt;应用在类型Bar上的BarModelBinder会用于针对参数bar的Model绑定，而参数baz则会使用默认的DefaultModelBinder&lt;/font&gt;。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; foo: FooModelBinder&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; bar: BarModelBinder&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt; baz: DefaultModelBinder&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;对于上面的这个例子，由于数据类型Baz没有关联ModelBinder注册到通过ModelBinders的静态属性Binders表示的全局ModelBinder列表中，所以才导致DoSomething的baz参数采用默认的DefaultModelBinder。如果我们实现针对数据类型Baz进行了相应的ModelBinder注册，那么被注册的ModelBinder将会自动用于该类型参数的Model绑定。同样是针对上面演示的这个实例，我们定义了如下一个实现了IModelBinder的BazModelBinder。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; BazModelBinder : IModelBinder&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;object&lt;/span&gt; BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;throw&lt;/span&gt; &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; NotImplementedException();&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt; }&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;现在我们希望使用这个BazModelBinder用于针对所有类型为Bar的参数的Model绑定，那么我们可以通过Global.asax在应用启动的时候进行如下的ModelBinder注册。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; MvcApplication : System.Web.HttpApplication&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color: #008000"&gt;//其他成员&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;protected&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; Application_Start()&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;         &lt;span style="color: #008000"&gt;//其他操作&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt;         ModelBinders.Binders.Add(&lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(Baz), &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; BazModelBinder());&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt;     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt; }&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;再次运行我们的程序，在浏览器中会得到如下的输出结果，从中可以清楚地看出我们注册的&lt;font color="#ff0000"&gt;BazModelBinder并用于baz参数的Model绑定&lt;/font&gt;。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; foo: FooModelBinder&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; bar: BarModelBinder&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt; baz: BazModelBinder&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;&lt;strong&gt;&lt;font size="4"&gt;&lt;font style="font-weight: bold"&gt;四、ModelBinderProvider &lt;/font&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;ASP.NET MVC的Model绑定系统还涉及到另一个重要的组件ModelBinderProvider。顾名思义，ModelBinderProvider专门用于提供相应的ModelBinder对象，它们均实现了&lt;a title="IModelBinderProvider Interface" href="http://msdn2.microsoft.com/gg402095.aspx"&gt;IModelBinderProvider&lt;/a&gt;面的代码片断所示，IModelBinderProvider接口定义了唯一的GetBinder方法用于根据数据类型获取相应的ModelBinder对象。不过在&lt;font color="#ff0000"&gt;ASP.NET MVC现有的应用编程接口中并没有定义任何一个实现该接口的ModelBinderProvider类型&lt;/font&gt;。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;interface&lt;/span&gt; IModelBinderProvider&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {    &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     IModelBinder GetBinder(Type modelType);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt; }&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;我们可以利用&lt;a title="ModelBinderProviders Class" href="http://msdn2.microsoft.com/gg416533.aspx"&gt;ModelBinderProviders&lt;/a&gt;为应用注册一组ModelBinderProvider对象为某个数据类型提供相应的ModelBinder。如下面的代码片断所示，静态类型ModelBinderProviders具有一个静态只读属性BinderProviders，其类型&lt;a title="ModelBinderProviderCollection Class" href="http://msdn2.microsoft.com/gg402083.aspx"&gt;ModelBinderProviderCollection&lt;/a&gt;实际上是一个型ModelBinderProvider的集合，该集合表示针对当前应用的ModelBinderProvider列表。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; ModelBinderProviders&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {    &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; ModelBinderProviderCollection BinderProviders { get; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;sealed&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; ModelBinderProviderCollection : Collection&amp;lt;IModelBinderProvider&amp;gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt; {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt;     &lt;span style="color: #008000"&gt;//省略成员&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt; }&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;通过ModelBinderProviders的静态属性BinderProviders表示的ModelBinderProvider列表最终被ModelBinderDictionary使用。如下面的代码片断所示，ModelBinderDictionary除了具有一个表示基于数据类型的ModelBinder字典（_innerDictionary字段）和一个默认ModelBinder（_defaultBinder）之外，还具有一个ModelBinderProvider列表（_modelBinderProviders字段）。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; ModelBinderDictionary&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color: #008000"&gt;//其他成员&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; IModelBinder _defaultBinder;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;readonly&lt;/span&gt; Dictionary&amp;lt;Type, IModelBinder&amp;gt; _innerDictionary;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; ModelBinderProviderCollection _modelBinderProviders;   &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt; }&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&lt;font color="#ff0000"&gt;当ModelBinderDictionary被创建的时候，通过ModelBinderProviders的静态属性BinderProviders表示的ModelBinderProvider列表会用于初始化_modelBinderProviders字段&lt;/font&gt;。围绕着ModelBinder的Model绑定系统中的核心组件之间的关系基本上可以通过下图所示的UML来表示。&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/artech/201205/201205210812043833.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/artech/201205/201205210812047704.png" width="475" height="259" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;当我们调用GetBinder或者指定数据类型对应的ModelBinder时，_innerDictionary字段表示的ModelBinder字典会被优先选择。如果数据类型在该字典中找不到，则选择使用通过_modelBinderProviders字段表示的ModelBinderProvider列表进行ModelBinder的提供。只有在两种ModelBinder提供方式均失败的情况下才会选择通过_innerDictionary字段表示的默认ModelBinder。也就是说，如果我们想为某个数据类型定制某种类型的ModelBinder，按照选择优先级具有如下几种方式供我们选择：&lt;/p&gt;&lt;ul&gt;  &lt;li&gt;将ModelBinderAttribute应用在Action方法的相应&lt;font color="#ff0000"&gt;参数&lt;/font&gt;上并指定相应的ModelBinder类型，或者在参数上应用一个自定义的CustomModelBinderAttribute特性。 &lt;/li&gt;  &lt;li&gt;将ModelBinderAttribute应用在数据&lt;font color="#ff0000"&gt;类型&lt;/font&gt;上并制定相应的ModelBinder类型，或者在数据类型上应用一个自定义的CustomModelBinderAttribute特性。 &lt;/li&gt;  &lt;li&gt;通过&lt;font color="#ff0000"&gt;ModelBinders的静态属性Binders&lt;/font&gt;实现针对基于某种数据类型的ModelBinder注册。 &lt;/li&gt;  &lt;li&gt;自定义&lt;font color="#ff0000"&gt;ModelBinderProvider&lt;/font&gt;实现基于某个数据类型的ModelBinder提供机制，并通过注册当通过ModelBinderProviders的静态属性BinderProviders表示的ModelBinderProvider列表中。 &lt;/li&gt;&lt;/ul&gt;&lt;p&gt;前面三种方式的ModelBinder提供机制我们已经通过实例演示过了，现在我们来演示基于自定义ModelBinderProvider的ModelBinder提供机制。在前面的例子中我们为Foo、Bar和Baz这三种数据类型创建了相应的ModelBinder（FooModelBinder、BarModelBinder和BazModelBinder），现在我们创建如下一个自定义的ModelBinderProvider将两种（数据类型和ModelBinder对象）进行关联。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; MyModelBinderProvider : IModelBinderProvider&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; IModelBinder GetBinder(Type modelType)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (modelType == &lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(Foo))&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;         {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; FooModelBinder();&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt;         }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (modelType == &lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(Bar))&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum10"&gt;  10:&lt;/span&gt;         {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum11"&gt;  11:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; BazModelBinder();&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum12"&gt;  12:&lt;/span&gt;         }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum13"&gt;  13:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (modelType == &lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(Baz))&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum14"&gt;  14:&lt;/span&gt;         {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum15"&gt;  15:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; BazModelBinder();&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum16"&gt;  16:&lt;/span&gt;         }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum17"&gt;  17:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum18"&gt;  18:&lt;/span&gt;     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum19"&gt;  19:&lt;/span&gt; }&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;现在我们需要通过利用Global.asax通过如下的方式在应用启动时将一个我们自定义的MyModelBinderProvider注册到通过ModelBinderProviders的静态属性BinderProviders表示的ModelBinderProvider列表中。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; MvcApplication : System.Web.HttpApplication&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color: #008000"&gt;//其他成员&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;protected&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; Application_Start()&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;         &lt;span style="color: #008000"&gt;//其他操作&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt;        ModelBinderProviders.BinderProviders.Add(&lt;span style="color: #0000ff"&gt;new&lt;/span&gt; MyModelBinderProvider());&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt;     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt; }&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;由于MyModelBinderProvider实现了针对Foo、Bar和Baz三种数据类型的ModelBinder的提供，所以我们可以&lt;font color="#ff0000"&gt;将应用在Action方法参数和数据类型上的ModelBinderAttribute特性删除&lt;/font&gt;。再次运行我们的程序，会在浏览器中得到如下的输出结果，从中可以看到DoSomething方法的三个参数此时采用了我们期望的ModelBinder类型。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; foo: FooModelBinder&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; bar: BarModelBinder&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt; baz: BazModelBinder&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;img src="http://www.cnblogs.com/artech/aggbug/2511086.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/artech/archive/2012/05/21/model-binder-provision.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/artech/archive/2012/05/19/value-provider-03.html</id><title type="text">ASP.NET MVC以ValueProvider为核心的值提供系统: ValueProviderFactory</title><summary type="text">在ASP.NET Model绑定系统中，用于提供数据值的ValueProvider对象通过ValueProviderFactory来创建。在ASP.NET MVC应用编程接口中，ValueProviderFactory继承自ValueProviderFactory类。本篇文章只要介绍基于ValueProviderFactory的ValueProvider的提供机制，以及如何通过自定义ValueProviderFactory实现我们需要的数据值的绑定方式</summary><published>2012-05-18T23:20:00Z</published><updated>2012-05-18T23:20:00Z</updated><author><name>Artech</name><uri>http://www.cnblogs.com/artech/</uri></author><link rel="alternate" href="http://www.cnblogs.com/artech/archive/2012/05/19/value-provider-03.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/artech/archive/2012/05/19/value-provider-03.html"/><content type="html">&lt;p&gt;在ASP.NET Model绑定系统中，用于提供数据值的ValueProvider对象通过ValueProviderFactory来创建。在ASP.NET MVC应用编程接口中，ValueProviderFactory继承自&lt;a title="ValueProviderFactory Class" href="http://msdn2.microsoft.com/ee872506.aspx"&gt;ValueProviderFactory&lt;/a&gt;类。本篇文章只要介绍基于ValueProviderFactory的ValueProvider的提供机制，以及如何通过自定义ValueProviderFactory实现我们需要的数据值的绑定方式。[本文已经同步到《&lt;a href="http://www.cnblogs.com/artech/archive/2012/04/10/how-mvc-works.html"&gt;How ASP.NET MVC Works?&lt;/a&gt;》中]&lt;/p&gt;  &lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;   &lt;p&gt;目录      &lt;br /&gt;一、ValueProviderFactory       &lt;br /&gt;二、ValueProviderFactory的注册       &lt;br /&gt;三、实例演示：创建一个自定义ValueProviderFactory&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;strong&gt;&lt;font size="4"&gt;&lt;font style="font-weight: bold"&gt;一、ValueProviderFactory&lt;/font&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;如下面的代码片断所示，ValueProviderFactory是一个抽象类，唯一的抽象方法GetValueProvider用于实现基于指定Controller上下文的ValueProvider创建。&lt;/p&gt;  &lt;div id="codeSnippetWrapper"&gt;   &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;     &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;abstract&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; ValueProviderFactory&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;abstract&lt;/span&gt; IValueProvider GetValueProvider(ControllerContext controllerContext);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt; }&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;下面的列表列出了定义在Model绑定系统中的6个原生的ValueProviderFactory：&lt;/p&gt;&lt;ul&gt;  &lt;li&gt;ChildActionValueProviderFactory：根据给定的Controller上下文创建一个ChildActionValueProvider对象。 &lt;/li&gt;  &lt;li&gt;FormValueProviderFactory：根据给定的Controller上下文创建一个FormValueProvider对象。 &lt;/li&gt;  &lt;li&gt;JsonValueProviderFactory：将以JSON形式表示的请求数据转换成一个Dictionary&amp;lt;string, object&amp;gt;对象，并最终创建一个DictionaryValueProvider&amp;lt;object&amp;gt;对象。 &lt;/li&gt;  &lt;li&gt;RouteDataValueProviderFactory：根据给定的Controller上下文创建一个RouteDataValueProvider对象。 &lt;/li&gt;  &lt;li&gt;QueryStringValueProviderFactory：根据给定的Controller上下文创建一个QueryStringValueProvider对象。 &lt;/li&gt;  &lt;li&gt;HttpFileCollectionValueProviderFactory：根据给定的Controller上下文创建一个HttpFileCollectionValueProvider对象。 &lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;&lt;font size="4"&gt;&lt;font style="font-weight: bold"&gt;二、ValueProviderFactory的注册&lt;/font&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;ValueProviderFactory在ASP.NET MVC应用中的注册通过静态类型&lt;a title="ValueProviderFactories Class" href="http://msdn2.microsoft.com/ee872451.aspx"&gt;ValueProviderFactories&lt;/a&gt;实现。如下面的代码片断所示，ValueProviderFactories具有一个静态只读属性Factories返回一个表示ValueProviderFactory集合的ValueProviderFactoryCollection类型。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; ValueProviderFactories&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; ValueProviderFactoryCollection Factories { get; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; ValueProviderFactoryCollection : Collection&amp;lt;ValueProviderFactory&amp;gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt; { &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; ValueProviderFactoryCollection();&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; ValueProviderFactoryCollection(IList&amp;lt;ValueProviderFactory&amp;gt; list);    &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum10"&gt;  10:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; IValueProvider GetValueProvider(ControllerContext controllerContext);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum11"&gt;  11:&lt;/span&gt; }&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;ValueProviderFactoryCollection的GetValueProvider方法返回的是一个ValueProviderCollection对象，集合中的每个ValueProvider通过对应的ValueProviderFactory来创建。&lt;font color="#ff0000"&gt;ValueProviderFactory在ValueProviderFactoryCollection集合中的先后次序决定了创建的ValueProvider在ValueProviderCollection中的次序，而次序决定了使用优先级&lt;/font&gt;。&lt;/p&gt;&lt;p&gt;在默认的情况下ValueProviderFactories的Factories属性表示的ValueProviderFactoryCollection包含了上面我们介绍的6种ValueProviderFactory，次序（优先级）为：ChildActionValueProviderFactory、FormValueProviderFactory、JsonValueProviderFactory、RouteDataValueProviderFactory、QueryStringValueProviderFactory和。&lt;font color="#ff0000"&gt;如果具有相同的名称的请求书去同时存在于请求表单和查询字符串中，前者会被选用&lt;/font&gt;。&lt;/p&gt;&lt;p&gt;以ValueProvider为核心的值提供系统中涉及到了三类组件/类型，即用于具体实现数据值提供的ValueProvider，ValueProvider通过ValueProviderFactotry，而ValueProviderFactotry通过ValueProviderFactotries进行注册。图5-4所示的UML体现了三者之间的关系。&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/artech/201205/201205190719461931.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/artech/201205/201205190719469390.png" width="447" height="373" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;font size="4"&gt;&lt;font style="font-weight: bold"&gt;三、实例演示：创建一个自定义ValueProviderFactory&lt;/font&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;ASP.NET MVC提供的6种ValueProviderFactory基本上已经可以满足我们绝大部分Model绑定需求，不过对于一些比较极端的场景，我们有可能需要自定义ValueProviderFactory。作为演示，我们创建一个&lt;font color="#ff0000"&gt;以HTTP请求报头集合作为数据源&lt;/font&gt;的自定义ValueProviderFactory。&lt;/p&gt;&lt;p&gt;我们将自定义的ValueProviderFactory命名为HttpHeaderValueProviderFactory。如下面的代码片断所示，HttpHeaderValueProviderFactory的定义非常简单，在重写的GetValueProvider方法中，我们将针对指定的Controller上下文得到HTTP报头集合，并借此创建NameValueCollection对象。由于作为报头名称具有“-”字符，为了与参数命名规则相匹配，我们将该字符剔除。最终创建的实际上是一个NameValueCollectionValueProvider对象。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; HttpHeaderValueProviderFactory : ValueProviderFactory&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {   &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;override&lt;/span&gt; IValueProvider GetValueProvider(ControllerContext controllerContext)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;         NameValueCollection requestData = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; NameValueCollection();&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;         var headers = controllerContext.RequestContext.HttpContext.Request.Headers;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;foreach&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; key &lt;span style="color: #0000ff"&gt;in&lt;/span&gt; headers.Keys)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt;         { &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt;             requestData.Add(key.Replace(&lt;span style="color: #006080"&gt;&amp;quot;-&amp;quot;&lt;/span&gt;,&lt;span style="color: #006080"&gt;&amp;quot;&amp;quot;&lt;/span&gt;),headers[key]);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum10"&gt;  10:&lt;/span&gt;         }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum11"&gt;  11:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; NameValueCollectionValueProvider(requestData, CultureInfo.InvariantCulture);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum12"&gt;  12:&lt;/span&gt;     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum13"&gt;  13:&lt;/span&gt; }&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;我们通过Visual Studio的ASP.NET MVC项目模板创建一个空Web应用，并创建一个具有如下定义的HomeController。默认的Action方法Index具有一系列的参数，从参数名称我们可以看出它们代表一些常用的HTTP报头。我们最终将代表HTTP报头的参数值呈现出来。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; HomeController : Controller&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {       &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; Index(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; connection, &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; accept, &lt;span style="color: #0000ff"&gt;string&lt;/span&gt;  acceptCharset, &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; acceptEncoding ,&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; acceptLanguage, &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; host, &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; userAgent)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;         Response.Write(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;.Format(&lt;span style="color: #006080"&gt;&amp;quot;{0}: {1}&amp;lt;br/&amp;gt;&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;Connection&amp;quot;&lt;/span&gt;, accept));&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt;         Response.Write(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;.Format(&lt;span style="color: #006080"&gt;&amp;quot;{0}: {1}&amp;lt;br/&amp;gt;&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;Accept-Charset&amp;quot;&lt;/span&gt;, acceptCharset));&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt;         Response.Write(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;.Format(&lt;span style="color: #006080"&gt;&amp;quot;{0}: {1}&amp;lt;br/&amp;gt;&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;Accept Encoding&amp;quot;&lt;/span&gt;, acceptEncoding));&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt;         Response.Write(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;.Format(&lt;span style="color: #006080"&gt;&amp;quot;{0}: {1}&amp;lt;br/&amp;gt;&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;Accept-Language&amp;quot;&lt;/span&gt;, acceptLanguage));&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum10"&gt;  10:&lt;/span&gt;         Response.Write(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;.Format(&lt;span style="color: #006080"&gt;&amp;quot;{0}: {1}&amp;lt;br/&amp;gt;&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;Host&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;host&amp;quot;&lt;/span&gt;));&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum11"&gt;  11:&lt;/span&gt;         Response.Write(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;.Format(&lt;span style="color: #006080"&gt;&amp;quot;{0}: {1}&amp;lt;br/&amp;gt;&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;User-Agent&amp;quot;&lt;/span&gt;, userAgent));&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum12"&gt;  12:&lt;/span&gt;     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum13"&gt;  13:&lt;/span&gt; }&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;然后利用Global.asax中按照如下的方式利用静态类型对我们自定义的HttpHeaderValueProviderFactory进行注册。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; MvcApplication : System.Web.HttpApplication&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {  &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color: #008000"&gt;//其他成员&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;protected&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; Application_Start()&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;         &lt;span style="color: #008000"&gt;//其他操作&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt;         ValueProviderFactories.Factories.Add(&lt;span style="color: #0000ff"&gt;new&lt;/span&gt; HttpHeaderValueProviderFactory());&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt;     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt; }&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;当我们运行该程序的时候，会在浏览器中呈现如下的输出结果，而输出的结果正是当前请求的HTTP报头列表。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; Connection: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt; Accept Encoding: gzip,deflate,sdch&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt; Accept-Language: en-US,en;q=0.8&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt; Host: host&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt; User-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.162 Safari/535.19&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;  &lt;br /&gt;&lt;a href="http://www.cnblogs.com/artech/archive/2012/05/17/value-provider-01.html"&gt;ASP.NET MVC以ValueProvider为核心的值提供系统: NameValueCollectionValueProvider&lt;/a&gt;   &lt;br /&gt;&lt;a href="http://www.cnblogs.com/artech/archive/2012/05/18/value-provider-02.html"&gt;ASP.NET MVC以ValueProvider为核心的值提供系统: DictionaryValueProvider&lt;/a&gt;   &lt;br /&gt;&lt;a href="http://www.cnblogs.com/artech/archive/2012/05/19/value-provider-03.html"&gt;ASP.NET MVC以ValueProvider为核心的值提供系统: ValueProviderFactory&lt;/a&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/artech/aggbug/2508572.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/artech/archive/2012/05/19/value-provider-03.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/artech/archive/2012/05/18/value-provider-02.html</id><title type="text">ASP.NET MVC以ValueProvider为核心的值提供系统: DictionaryValueProvider</title><summary type="text">NameValueCollectionValueProvider采用一个NameValueCollection作为数据源，DictionnaryValueProvider的数据源类型自然就是一个Dictionnary。NameValueCollection和Dictionnary都是一个键值对的集合，它们之间的不同之处在NameValueCollection运行元素具有相同的Key，Dictionnary却要求元素的Key具有唯一性</summary><published>2012-05-18T00:22:00Z</published><updated>2012-05-18T00:22:00Z</updated><author><name>Artech</name><uri>http://www.cnblogs.com/artech/</uri></author><link rel="alternate" href="http://www.cnblogs.com/artech/archive/2012/05/18/value-provider-02.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/artech/archive/2012/05/18/value-provider-02.html"/><content type="html">&lt;p&gt;NameValueCollectionValueProvider采用一个NameValueCollection作为数据源，DictionnaryValueProvider的数据源类型自然就是一个Dictionnary。NameValueCollection和Dictionnary都是一个键值对的集合，它们之间的不同之处在NameValueCollection运行元素具有相同的Key，Dictionnary却要求元素的Key具有唯一性。[本文已经同步到《&lt;a href="http://www.cnblogs.com/artech/archive/2012/04/10/how-mvc-works.html"&gt;How ASP.NET MVC Works?&lt;/a&gt;》中]&lt;/p&gt;  &lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;   &lt;p&gt;目录     &lt;br /&gt;一、DictionaryValueProvider&amp;lt;TValue&amp;gt;      &lt;br /&gt;二、RouteDataValueProvider      &lt;br /&gt;三、HttpFileCollectionValueProvider      &lt;br /&gt;四、ChildActionValueProvider      &lt;br /&gt;五、实例演示：ChildActionValueProvider的值提供机制      &lt;br /&gt;六、ValueProviderCollection&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;strong&gt;&lt;font size="4"&gt;&lt;font style="font-weight: bold"&gt;一、DictionaryValueProvider&amp;lt;TValue&amp;gt;&lt;/font&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;DictionnaryValueProvider的类型全名为System.Web.Mvc.DictionaryValueProvider&amp;lt;TValue&amp;gt;，如下面的代码片断所示，DictionaryValueProvider&amp;lt;TValue&amp;gt;实现了IEnumerableValueProvider和IValueProvider接口，构造函数接受一个IDictionary&amp;lt;string, TValue&amp;gt;对象，该对象表示作为数据源的字典。定义在DictionaryValueProvider&amp;lt;TValue&amp;gt;中所有方法的逻辑与定义在NameValueCollectionValueProvider中的同名方法并没有本质区别。&lt;/p&gt;  &lt;div id="codeSnippetWrapper"&gt;   &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;     &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; DictionaryValueProvider&amp;lt;TValue&amp;gt; : IEnumerableValueProvider, IValueProvider&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; DictionaryValueProvider(IDictionary&amp;lt;&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;, TValue&amp;gt; dictionary, CultureInfo culture);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;virtual&lt;/span&gt; &lt;span style="color: #0000ff"&gt;bool&lt;/span&gt; ContainsPrefix(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; prefix);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;virtual&lt;/span&gt; IDictionary&amp;lt;&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;string&lt;/span&gt;&amp;gt; GetKeysFromPrefix(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; prefix);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;virtual&lt;/span&gt; ValueProviderResult GetValue(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; key);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt; }&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;&lt;font size="4"&gt;&lt;font style="font-weight: bold"&gt;&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="4"&gt;&lt;font style="font-weight: bold"&gt;&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="4"&gt;&lt;font style="font-weight: bold"&gt;二、RouteDataValueProvider&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;将当前路由数据作为数据源的&lt;a title="RouteDataValueProvider Class" href="http://msdn2.microsoft.com/ee703614.aspx"&gt;RouteDataValueProvider&lt;/a&gt;继承自DictionaryValueProvider&amp;lt;TValue&amp;gt;。如下面的代码片断所示，基于当前Controller上下文构建的RouteDataValueProvider直接将表示当前路由数据的RouteData对象的Values属性（这是一个RouteValueDictionary对象）作为数据来源。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;sealed&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; RouteDataValueProvider : DictionaryValueProvider&amp;lt;&lt;span style="color: #0000ff"&gt;object&lt;/span&gt;&amp;gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; RouteDataValueProvider(ControllerContext controllerContext) : &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;base&lt;/span&gt;(controllerContext.RouteData.Values, CultureInfo.InvariantCulture)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt; }&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;&lt;strong&gt;&lt;font size="4"&gt;&lt;font style="font-weight: bold"&gt;三、HttpFileCollectionValueProvider&lt;/font&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;我们可以通过类型为file的输入元素进行文件的上传，在表示HTTP请求的HttpRequestBase对象中，上传文件通过只读属性Files表示。从下面的代码片断所示，该属性类型为HttpFileCollectionBase，是一个元素类型为HttpPostedFileBase的集合。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;abstract&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; HttpRequestBase&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {   &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;virtual&lt;/span&gt; HttpFileCollectionBase Files { get; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;abstract&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; HttpFileCollectionBase : NameObjectCollectionBase, ICollection, IEnumerable&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt; {   &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;virtual&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt;[] AllKeys { get; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;override&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; Count { get; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;virtual&lt;/span&gt; HttpPostedFileBase &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;[&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; index] { get; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum10"&gt;  10:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;virtual&lt;/span&gt; HttpPostedFileBase &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;[&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; name] { get; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum11"&gt;  11:&lt;/span&gt; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum12"&gt;  12:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;abstract&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; HttpPostedFileBase&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum13"&gt;  13:&lt;/span&gt; {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum14"&gt;  14:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;virtual&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; SaveAs(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; filename);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum15"&gt;  15:&lt;/span&gt;&amp;nbsp; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum16"&gt;  16:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;virtual&lt;/span&gt; &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; ContentLength { get; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum17"&gt;  17:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;virtual&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; ContentType { get; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum18"&gt;  18:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;virtual&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; FileName { get; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum19"&gt;  19:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;virtual&lt;/span&gt; Stream InputStream { get; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum20"&gt;  20:&lt;/span&gt; }&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;用于处理上传文件的Action方法通常定义类型为HttpPostedFileBase及其列表的参数来表示上传的文件，针对HttpPostedFileBase参数的Model绑定选用的数据就来源于表示当前请求的HttpRequestBase的Files属性，而具体参数值的提供最终通过具有如下定义的&lt;a title="HttpFileCollectionValueProvider Class" href="http://msdn2.microsoft.com/ee703643.aspx"&gt;HttpFileCollectionValueProvider&lt;/a&gt;来实现。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;sealed&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; HttpFileCollectionValueProvider : DictionaryValueProvider&amp;lt;HttpPostedFileBase[]&amp;gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {    &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; HttpFileCollectionValueProvider(ControllerContext controllerContext);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt; }&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;如上面的代码所示，HttpFileCollectionValueProvider继承自DictionaryValueProvider&amp;lt;TValue&amp;gt;，泛型参数TValue的类型为HttpPostedFileBase数组，这是因为在同一个表单中可以定义多个同名的文件输入元素，所以在以文件元素名称作为Key的字典中，字典元素的值自然就是一个HttpPostedFileBase的列表。&lt;/p&gt;&lt;p&gt;为了让读者对HttpFileCollectionValueProvider采用的针对上传文件的值对象提供机制具有一个深刻的认识，我们来进行一个简单的实例演示。在通过Visual Studio的ASP.NET MVC项目模板创建的空Web应用中创建一个具有如下定义的HomeController。该Controller类型中定义了两个Action方法，默认的Index方法会将默认的View呈现出来，DisplayPostedFiles方法则通过创建的HttpFileCollectionValueProvider对象将上传文件的文件名称呈现出来。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; HomeController : Controller&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; ActionResult Index()&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; View();&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt;     [HttpPost]&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; DisplayPostedFiles()&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt;     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum10"&gt;  10:&lt;/span&gt;         HttpFileCollectionValueProvider valueProvider = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; HttpFileCollectionValueProvider(ControllerContext);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum11"&gt;  11:&lt;/span&gt;         IEnumerable&amp;lt;HttpPostedFileBase&amp;gt; foo = (IEnumerable&amp;lt;HttpPostedFileBase&amp;gt;)valueProvider.GetValue(&lt;span style="color: #006080"&gt;"foo"&lt;/span&gt;).ConvertTo(&lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(IEnumerable&amp;lt;HttpPostedFileBase&amp;gt;));&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum12"&gt;  12:&lt;/span&gt;         IEnumerable&amp;lt;HttpPostedFileBase&amp;gt; bar =  (IEnumerable&amp;lt;HttpPostedFileBase&amp;gt;)valueProvider.GetValue(&lt;span style="color: #006080"&gt;"bar"&lt;/span&gt;).ConvertTo(&lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(IEnumerable&amp;lt;HttpPostedFileBase&amp;gt;));&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum13"&gt;  13:&lt;/span&gt;&amp;nbsp; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum14"&gt;  14:&lt;/span&gt;         Response.Write(&lt;span style="color: #006080"&gt;"foo&amp;lt;br/&amp;gt;"&lt;/span&gt;);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum15"&gt;  15:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;foreach&lt;/span&gt; (var file &lt;span style="color: #0000ff"&gt;in&lt;/span&gt; foo)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum16"&gt;  16:&lt;/span&gt;         {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum17"&gt;  17:&lt;/span&gt;             Response.Write(file.FileName + &lt;span style="color: #006080"&gt;"&amp;lt;br/&amp;gt;"&lt;/span&gt;);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum18"&gt;  18:&lt;/span&gt;         }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum19"&gt;  19:&lt;/span&gt;&amp;nbsp; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum20"&gt;  20:&lt;/span&gt;         Response.Write(&lt;span style="color: #006080"&gt;"&amp;lt;br/&amp;gt;bar&amp;lt;br/&amp;gt;"&lt;/span&gt;);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum21"&gt;  21:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;foreach&lt;/span&gt; (var file &lt;span style="color: #0000ff"&gt;in&lt;/span&gt; bar)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum22"&gt;  22:&lt;/span&gt;         {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum23"&gt;  23:&lt;/span&gt;             Response.Write(file.FileName + &lt;span style="color: #006080"&gt;"&amp;lt;br/&amp;gt;"&lt;/span&gt;);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum24"&gt;  24:&lt;/span&gt;         }            &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum25"&gt;  25:&lt;/span&gt;     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum26"&gt;  26:&lt;/span&gt; }&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;在DisplayPostedFiles方法中，我们针对当前Controller上下文创建HttpFileCollectionValueProvider对象，然后分别将字符&amp;#8220;foo&amp;#8221;和&amp;#8220;bar&amp;#8221;作为Key得到两个HttpPostedFileBase对象列表，并将它们的文件名打印出来。下面的代码表示Action方法Index对应的View。在一个针对Action方法DisplayPostedFiles的表单中我们定义了三个文件输入元素，其中前两个名称为&amp;#8220;foo&amp;#8221;和&amp;#8220;bar&amp;#8221;。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; @{&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt;    using(Html.BeginForm("DisplayPostedFiles","Home", &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;        FormMethod.Post,new {enctype="multipart/form-data"}))&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;    {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;        &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;ul&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;li&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;File 1: &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;input&lt;/span&gt; &lt;span style="color: #ff0000"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="file"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="foo"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;li&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;li&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;File 2: &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;input&lt;/span&gt; &lt;span style="color: #ff0000"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="file"&lt;/span&gt;  &lt;span style="color: #ff0000"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="foo"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;li&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;li&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;File 3: &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;input&lt;/span&gt; &lt;span style="color: #ff0000"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="file"&lt;/span&gt;  &lt;span style="color: #ff0000"&gt;name&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="bar"&lt;/span&gt;&lt;span style="color: #0000ff"&gt;/&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;li&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt;        &lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;ul&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;  &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum10"&gt;  10:&lt;/span&gt;        &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;input&lt;/span&gt; &lt;span style="color: #ff0000"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="submit"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;value&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="提交"&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;       &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum11"&gt;  11:&lt;/span&gt;     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum12"&gt;  12:&lt;/span&gt; }&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;当我们运行该程序的时候，浏览器上会出现一个包含三个文件输入元素和提交按钮的页面。然后我们从本地选择任意三个文件（比如text1.txt、text2.txt和text2.txt）并点击&amp;#8220;提交&amp;#8221;按钮，界面上会出现如下所示的输出结果。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; foo&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; text1.txt&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt; text2.txt&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;&amp;nbsp; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt; bar&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt; text3.txt&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;&lt;strong&gt;&lt;font size="4"&gt;&lt;font style="font-weight: bold"&gt;四、ChildActionValueProvider&lt;/font&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;子Action和普通意义上的Action的不同之处在于它不能用于响应来自客户端的请求，而在某个View中被调用以生成某个部分的HTML。View中针对某个子Action方法的调用通过如下所示的HtmlHelper的扩展方法Action来实现。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; public static class ChildActionExtensions&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     //其他成员&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;     public static MvcHtmlString Action(this HtmlHelper htmlHelper, string actionName);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;     public static MvcHtmlString Action(this HtmlHelper htmlHelper, string actionName, object routeValues);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;     public static MvcHtmlString Action(this HtmlHelper htmlHelper, string actionName, string controllerName);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt;     public static MvcHtmlString Action(this HtmlHelper htmlHelper, string actionName, RouteValueDictionary routeValues);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt;     public static MvcHtmlString Action(this HtmlHelper htmlHelper, string actionName, string controllerName, object routeValues);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt;     public static MvcHtmlString Action(this HtmlHelper htmlHelper, string actionName, string controllerName, RouteValueDictionary routeValues);  &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum10"&gt;  10:&lt;/span&gt; }&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;顾名思义，&lt;a title="ChildActionValueProvider Class" href="http://msdn2.microsoft.com/gg480724.aspx"&gt;ChildActionValueProvider&lt;/a&gt;专门服务于针对子Action方法参数的Model绑定。如下面的代码片断所示，ChildActionValueProvider依然是DictionaryValueProvider&amp;lt;TValue&amp;gt;的继承者，不过这里的泛型参数类型Object。那么在作为数据源的字典中，具体的Key和Value究竟是怎样一个对象呢？&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;sealed&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; ChildActionValueProvider : DictionaryValueProvider&amp;lt;&lt;span style="color: #0000ff"&gt;object&lt;/span&gt;&amp;gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; ChildActionValueProvider(ControllerContext controllerContext);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;override&lt;/span&gt; ValueProviderResult GetValue(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; key);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt; }&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;当我们创建针对指定的Controller上下文创建一个ChildActionValueProvider对象时，会&lt;font color="#ff0000"&gt;获取描述针对该上下文路由信息的RouteData对象，并将其Values属性表示的RouteValueDictionary对象作为其数据源&lt;/font&gt;，这可以从如下所示的ChildActionValueProvider的构造函数定义看出来。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;sealed&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; ChildActionValueProvider : DictionaryValueProvider&amp;lt;&lt;span style="color: #0000ff"&gt;object&lt;/span&gt;&amp;gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color: #008000"&gt;//其他成员   &lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; ChildActionValueProvider(ControllerContext controllerContext) :  &lt;span style="color: #0000ff"&gt;base&lt;/span&gt;(controllerContext.RouteData.Values, CultureInfo.InvariantCulture)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt; }&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;但是ChildActionValueProvider的GetValue方法获取的值却&lt;font color="#ff0000"&gt;并不是简单地来源于构造时针对当前上下文的路由信息&lt;/font&gt;，不然ChildActionValueProvider就和RouteDataValueProvider没有什么分别了。实际上，ChildActionValueProvider的GetValue方法获取的值来源于调用HtmHelper的扩展方法Action时通过参数routeValues指定的RouteValueDictionary。&lt;/p&gt;&lt;p&gt;现在我们来简单介绍一下定义在ChildActionValueProvider的GetValue方法中的对象值的提供机制。如下面的代码片断所示，ChildActionValueProvider具有一个字符串类型的静态字段&lt;font color="#ff0000"&gt;_childActionValuesKey&lt;/font&gt;。当该类型第一次被加载时，该字段被初始化成一个GUID。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;sealed&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; ChildActionValueProvider : DictionaryValueProvider&amp;lt;&lt;span style="color: #0000ff"&gt;object&lt;/span&gt;&amp;gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color: #008000"&gt;//其他成员&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; _childActionValuesKey = Guid.NewGuid().ToString();&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt; }&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;在某个View中通过HtmlHelper的扩展方法Action执行子Action方法时，如果通过参数routeValues指定的RouteValueDictionary不为空，会基于这个对象创建一个DictionaryValueProvider&amp;lt;TValue&amp;gt;对象。然后将这个对象添加到通过routeValues表示的原始的RouteValueDictionary对象中，对应的Key就是ChildActionValueProvider的静态属性_childActionValuesKey表示的GUID。&lt;/p&gt;&lt;p&gt;这个RouteValueDictionary被进一步封装成表示请求上下文的RequestContext对象，目标子Action所在的Controller会在该请求上下文中被激活，而在Controller激活过程中表示Controller上下文的ControllerContext被创建出来，毫无疑问它包含了之前创建的RouteValueDictionary对象。而我们针对当前Controller上下文创建ChildActionValueProvider的时候指定的作为数据源的RouteValueDictionary对象就是这么一个对象。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; @Html.Action("XxxChildAction", new {Foo=123, Bar = 456, Baz=789})&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;举个例子，假设我们在某个View中如果如下的方式调用当前Controller的子Action方法 XxxChildAction，并指定相应的路由数据（Foo、Bar和Baz）。最终作为ChildActionValueProvider数据源的Dictionary&amp;lt;string,object&amp;gt;对象结构如下图所示。&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/artech/201205/201205180822027378.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/artech/201205/201205180822036473.png" width="395" height="301" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;当调用ChildActionValueProvider的GetValue方法获取指定Key的值时，实际上并不会直接根据指定的Key去获取对应的值，而是&lt;font color="#ff0000"&gt;根据通过其静态字段_childActionValuesKey值去获取对应的DictionaryValueProvider&amp;lt;object&amp;gt;对象&lt;/font&gt;。然后再调用该对象的GetValue根据指定的Key去获得相应的值。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;font size="4"&gt;&lt;font style="font-weight: bold"&gt;五、实例演示：ChildActionValueProvider的值提供机制&lt;/font&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;为了印证上面介绍的关于ChildActionValueProvider的值提供机制，我们来演示一个简单的实例。在进行演示之前有一个点需要作一下简单说明，对于DictionaryValueProvider&amp;lt;TValue&amp;gt;对象来说，最终作为其数据源的通过私有字段_values表示的一个Dictionary&amp;lt;string, ValueProviderResult对象。当我们调用GetValue方法是，只需要根据指定的Key从该字典对象中返回相应的ValueProviderResult即可。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; DictionaryValueProvider&amp;lt;TValue&amp;gt; : IEnumerableValueProvider, IValueProvider&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color: #008000"&gt;//其他成员&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;readonly&lt;/span&gt; Dictionary&amp;lt;&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;, ValueProviderResult&amp;gt; _values;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt; }&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;在通过Visual Studio的ASP.NET MVC 项目模板创建的空Web应用中定义如下一个默认的HomeController。默认的Action方法Index仅仅是将默认的View呈现出来而已，并没有特别之处。在另一个Action方法DisplayRouteData中，我们名称分别为Foo、Bar和Baz的三个路由数据篡改成&amp;#8220;abc&amp;#8221;、&amp;#8220;ijk&amp;#8221;和&amp;#8220;zyz&amp;#8221;。然后根据当前Controller上下文创建一个ChildActionValueProvider对象，并通过反射的方式获取通过它的私有字段_values表示的Dictionary&amp;lt;string, ValueProviderResult对象。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; HomeController : Controller&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; ActionResult Index()&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; View();&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt;&amp;nbsp; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; ActionResult DisplayRouteData()&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt;     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum10"&gt;  10:&lt;/span&gt;         ControllerContext.RouteData.Values[&lt;span style="color: #006080"&gt;"Foo"&lt;/span&gt;] = &lt;span style="color: #006080"&gt;"abc"&lt;/span&gt;;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum11"&gt;  11:&lt;/span&gt;         ControllerContext.RouteData.Values[&lt;span style="color: #006080"&gt;"Bar"&lt;/span&gt;] = &lt;span style="color: #006080"&gt;"ijk"&lt;/span&gt;;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum12"&gt;  12:&lt;/span&gt;         ControllerContext.RouteData.Values[&lt;span style="color: #006080"&gt;"Baz"&lt;/span&gt;] = &lt;span style="color: #006080"&gt;"xyz"&lt;/span&gt;;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum13"&gt;  13:&lt;/span&gt;&amp;nbsp; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum14"&gt;  14:&lt;/span&gt;         StringBuilder sb = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; StringBuilder();&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum15"&gt;  15:&lt;/span&gt;         ChildActionValueProvider valueProvider = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; ChildActionValueProvider(ControllerContext);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum16"&gt;  16:&lt;/span&gt;         FieldInfo valuesField = &lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(DictionaryValueProvider&amp;lt;&lt;span style="color: #0000ff"&gt;object&lt;/span&gt;&amp;gt;).GetField(&lt;span style="color: #006080"&gt;"_values"&lt;/span&gt;, BindingFlags.Instance|BindingFlags.NonPublic);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum17"&gt;  17:&lt;/span&gt;         Dictionary&amp;lt;&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;, ValueProviderResult&amp;gt; values = (Dictionary&amp;lt;&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;, ValueProviderResult&amp;gt;)valuesField.GetValue(valueProvider);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum18"&gt;  18:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;foreach&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; key &lt;span style="color: #0000ff"&gt;in&lt;/span&gt; values.Keys)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum19"&gt;  19:&lt;/span&gt;         {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum20"&gt;  20:&lt;/span&gt;             sb.Append(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;.Format(&lt;span style="color: #006080"&gt;"{0}: {1}&amp;lt;br/&amp;gt;"&lt;/span&gt;, key, values[key].RawValue));&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum21"&gt;  21:&lt;/span&gt;             DictionaryValueProvider&amp;lt;&lt;span style="color: #0000ff"&gt;object&lt;/span&gt;&amp;gt; innerValueProvider = values[key].RawValue &lt;span style="color: #0000ff"&gt;as&lt;/span&gt; DictionaryValueProvider&amp;lt;&lt;span style="color: #0000ff"&gt;object&lt;/span&gt;&amp;gt;;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum22"&gt;  22:&lt;/span&gt;             &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (innerValueProvider == &lt;span style="color: #0000ff"&gt;null&lt;/span&gt;)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum23"&gt;  23:&lt;/span&gt;             {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum24"&gt;  24:&lt;/span&gt;                 &lt;span style="color: #0000ff"&gt;continue&lt;/span&gt;;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum25"&gt;  25:&lt;/span&gt;             }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum26"&gt;  26:&lt;/span&gt;             sb.Append(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;.Format(&lt;span style="color: #006080"&gt;"&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;{0}: {1}&amp;lt;br/&amp;gt;"&lt;/span&gt;, &lt;span style="color: #006080"&gt;"Foo"&lt;/span&gt;, innerValueProvider.GetValue(&lt;span style="color: #006080"&gt;"Foo"&lt;/span&gt;).RawValue));&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum27"&gt;  27:&lt;/span&gt;             sb.Append(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;.Format(&lt;span style="color: #006080"&gt;"&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;{0}: {1}&amp;lt;br/&amp;gt;"&lt;/span&gt;, &lt;span style="color: #006080"&gt;"Bar"&lt;/span&gt;, innerValueProvider.GetValue(&lt;span style="color: #006080"&gt;"Bar"&lt;/span&gt;).RawValue));&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum28"&gt;  28:&lt;/span&gt;             sb.Append(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;.Format(&lt;span style="color: #006080"&gt;"&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;{0}: {1}&amp;lt;br/&amp;gt;"&lt;/span&gt;, &lt;span style="color: #006080"&gt;"Baz"&lt;/span&gt;, innerValueProvider.GetValue(&lt;span style="color: #006080"&gt;"Baz"&lt;/span&gt;).RawValue));&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum29"&gt;  29:&lt;/span&gt;         }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum30"&gt;  30:&lt;/span&gt;&amp;nbsp; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum31"&gt;  31:&lt;/span&gt;         sb.Append(&lt;span style="color: #006080"&gt;"&amp;lt;br/&amp;gt;ChildActionValueProvider.GetValue()&amp;lt;br/&amp;gt;"&lt;/span&gt;);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum32"&gt;  32:&lt;/span&gt;         sb.Append(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;.Format(&lt;span style="color: #006080"&gt;"{0}: {1}&amp;lt;br/&amp;gt;"&lt;/span&gt;, &lt;span style="color: #006080"&gt;"Foo"&lt;/span&gt;, valueProvider.GetValue(&lt;span style="color: #006080"&gt;"Foo"&lt;/span&gt;).RawValue));&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum33"&gt;  33:&lt;/span&gt;         sb.Append(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;.Format(&lt;span style="color: #006080"&gt;"{0}: {1}&amp;lt;br/&amp;gt;"&lt;/span&gt;, &lt;span style="color: #006080"&gt;"Bar"&lt;/span&gt;, valueProvider.GetValue(&lt;span style="color: #006080"&gt;"Bar"&lt;/span&gt;).RawValue));&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum34"&gt;  34:&lt;/span&gt;         sb.Append(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;.Format(&lt;span style="color: #006080"&gt;"{0}: {1}&amp;lt;br/&amp;gt;"&lt;/span&gt;, &lt;span style="color: #006080"&gt;"Baz"&lt;/span&gt;, valueProvider.GetValue(&lt;span style="color: #006080"&gt;"Baz"&lt;/span&gt;).RawValue));            &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum35"&gt;  35:&lt;/span&gt;&amp;nbsp; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum36"&gt;  36:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; Content(sb.ToString());&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum37"&gt;  37:&lt;/span&gt;     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum38"&gt;  38:&lt;/span&gt; }&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;我们创建一个StringBuilder对象，并将用于输出获取到的Dictionary&amp;lt;string, ValueProviderResult&amp;gt;对象的Key和Value的HTML添加其中。在进行遍历过程中，如果ValueProviderResult对象的RawValue属性是一个DictionaryValueProvider&amp;lt;object&amp;gt;对象，则调用其GetValue方法得到Key分别为Foo、Bar和Baz的值。相应的输出的HTML一并添加到StringBuilder中。&lt;/p&gt;&lt;p&gt;在程序的最后，我们直接调用ChildActionValueProvider的GetValue方法获取针对Foo、Bar和Baz作为Key的值，并将输出Key和Value的HTML添加到StringBuilder中。最终针对生成的HTML字符串返回一个ContentResult对象。如下所示的代码反映Action方法Index对应的View的定义，在这里我们直接调用HtmlHelper的扩展方法Action执行定义在HomeController的Action方法DisplayRouteData，并指定了相应的路由数据（Foo、Bar和Baz）。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; @Html.Action("DisplayRouteData", new { Foo = 123, Bar = 456, Baz = 789 })&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;运行我们的程序会在浏览器中得到如下的输出结果。我们可以从中看到针对于Controller和Action名称的路由数据和调用HtmlHelper扩展方法Action指定的数据数据均在作为ChildActionValueProvider数据源的字典对象中。除此之外，还具有一个DictionaryValueProvider&amp;lt;object&amp;gt;对象，对应的Key是一个GUID，这正是我们上面介绍的针对在HtmlHelper扩展方法Action中指定的路由数据创建的DictionaryValueProvider&amp;lt;object&amp;gt;对象，而调用GetValue方法获取到的值最终是通过它提供的。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; Foo: abc&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; Bar: ijk&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt; Baz: xyz&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt; controller: Home&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt; action: DisplayRouteData&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt; 289594f6-dfba-45b9-8abb-158b4a582911: &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt;     System.Web.Mvc.DictionaryValueProvider`1[System.Object]&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt;     Foo: 123&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt;     Bar: 456&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum10"&gt;  10:&lt;/span&gt;     Baz: 789&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum11"&gt;  11:&lt;/span&gt;&amp;nbsp; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum12"&gt;  12:&lt;/span&gt; ChildActionValueProvider.GetValue()&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum13"&gt;  13:&lt;/span&gt; Foo: 123&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum14"&gt;  14:&lt;/span&gt; Bar: 456&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum15"&gt;  15:&lt;/span&gt; Baz: 789&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;&lt;strong&gt;&lt;font size="4"&gt;&lt;font style="font-weight: bold"&gt;六、ValueProviderCollection&lt;/font&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;类型&lt;a title="ValueProviderCollection Class" href="http://msdn2.microsoft.com/ee703521.aspx"&gt;ValueProviderCollection&lt;/a&gt;不仅仅表示一个ValueProvider对象的集合，还&lt;font color="#ffc000"&gt;作为一个单纯的ValueProvider来使用&lt;/font&gt;。如下面的代码片断所示，ValueProviderCollection不仅仅继承自Collection&amp;lt;IValueProvider&amp;gt;，还同时实现了IValueProvider、IEnumerableValueProvider和IUnvalidatedValueProvider三个接口。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; ValueProviderCollection : Collection&amp;lt;IValueProvider&amp;gt;, IUnvalidatedValueProvider, IEnumerableValueProvider, IValueProvider&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; ValueProviderCollection();&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; ValueProviderCollection(IList&amp;lt;IValueProvider&amp;gt; list);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;&amp;nbsp; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;virtual&lt;/span&gt; &lt;span style="color: #0000ff"&gt;bool&lt;/span&gt; ContainsPrefix(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; prefix);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;virtual&lt;/span&gt; IDictionary&amp;lt;&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;string&lt;/span&gt;&amp;gt; GetKeysFromPrefix(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; prefix);  &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;virtual&lt;/span&gt; ValueProviderResult GetValue(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; key);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;virtual&lt;/span&gt; ValueProviderResult GetValue(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; key, &lt;span style="color: #0000ff"&gt;bool&lt;/span&gt; skipValidation);   &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum10"&gt;  10:&lt;/span&gt; }&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;对于两个实现值提供机制的GetValue方法重载来说，ValueProviderCollection会遍历集合直到找到一个GetValue方法返回值不为Null的ValueProvider，而该返回值就是该方法的返回值。如果所有ValueProvider的GetValue方法均返回Null，则ValueProviderCollection的GetValue方法也为Null。也就是说，&lt;font color="#ff0000"&gt;ValueProvider在集合中的先后次序决定了其使用优先级&lt;/font&gt;。&lt;/p&gt;&lt;p&gt;如果有任何一个ValueProvider的ContainsPrefix方法返回True，则ValueProviderCollection的ContainsPrefix也返回True。GetKeysFromPrefix方法的逻辑与GetValue方法类似，它会遍历作为集合中实现了IEnumerableValueProvider接口的所有ValueProvider对象，并将指定的前缀作为参数调用ContainsPrefix方法，如果返回值为True，则直接返回GetKeysFromPrefix方法的结果；否则返回一个空的Dictionary&amp;lt;string, string&amp;gt;对象。&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/artech/archive/2012/05/17/value-provider-01.html"&gt;ASP.NET MVC以ValueProvider为核心的值提供系统: NameValueCollectionValueProvider&lt;/a&gt;  &lt;br /&gt;&lt;a href="http://www.cnblogs.com/artech/archive/2012/05/18/value-provider-02.html"&gt;ASP.NET MVC以ValueProvider为核心的值提供系统: DictionaryValueProvider&lt;/a&gt;  &lt;br /&gt;&lt;a href="http://www.cnblogs.com/artech/archive/2012/05/19/value-provider-03.html"&gt;ASP.NET MVC以ValueProvider为核心的值提供系统: ValueProviderFactory&lt;/a&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/artech/aggbug/2507167.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/artech/archive/2012/05/18/value-provider-02.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/artech/archive/2012/05/17/value-provider-01.html</id><title type="text">ASP.NET MVC以ValueProvider为核心的值提供系统: NameValueCollectionValueProvider</title><summary type="text">在进行Model绑定过程中，需要根据基于Action方法参数的绑定上下文从请求数据中提取相应的数据以提供相应的数据。具体来说，Model绑定的数据具有多个来源，可能来源于Post的表单或者JSON字符串，或者来源于当前的路由数据，也可能来源于请求地址的插叙字符串。ASP.NET MVC将这种基于不同数据来源的数据获取/提供机制实现在一个叫做ValueProvider的组件中</summary><published>2012-05-17T01:04:00Z</published><updated>2012-05-17T01:04:00Z</updated><author><name>Artech</name><uri>http://www.cnblogs.com/artech/</uri></author><link rel="alternate" href="http://www.cnblogs.com/artech/archive/2012/05/17/value-provider-01.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/artech/archive/2012/05/17/value-provider-01.html"/><content type="html">&lt;p&gt;在进行Model绑定过程中，需要根据基于Action方法参数的绑定上下文从请求数据中提取相应的数据以提供相应的数据。具体来说，Model绑定的数据具有多个来源，可能来源于Post的表单或者JSON字符串，或者来源于当前的路由数据，也可能来源于请求地址的插叙字符串。ASP.NET MVC将这种基于不同数据来源的数据获取/提供机制实现在一个叫做ValueProvider的组件中。[本文已经同步到《&lt;a href="http://www.cnblogs.com/artech/archive/2012/04/10/how-mvc-works.html"&gt;How ASP.NET MVC Works?&lt;/a&gt;》中]&lt;/p&gt;  &lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;   &lt;p&gt;目录      &lt;br /&gt;一、IValueProvider与ValueProviderResult       &lt;br /&gt;二、NameValueCollectionValueProvider       &lt;br /&gt;三、两种前缀形式       &lt;br /&gt;四、实例演示：返回指定前缀的Key       &lt;br /&gt;五、FormValueProvider与QueryStringValueProvider&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;strong&gt;&lt;font size="4"&gt;&lt;font style="font-weight: bold"&gt;一、IValueProvider与ValueProviderResult&lt;/font&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;一般来讲，一个ValueProvider采用的数据源是一个字典类型的数据结构，我们通过它从这个字典中获取一个Key与当前绑定上下文匹配的值。ValueProvider实现了具有如下定义的接口&lt;a title="IValueProvider Interface" href="http://msdn2.microsoft.com/ee721287.aspx"&gt;IValueProvider&lt;/a&gt;，GetValue方法根据指定的Key从数据源中获取对应的值对象，这个Key是基于当前绑定上下文的。这个Key和存在于数据源中对应数据条目的Key可能并非完全一致，后者可能在前者基础上添加相应的前缀，而ContainsPrefix方法用于判断数据源字典的Key是否具有指定的前缀。&lt;/p&gt;  &lt;div id="codeSnippetWrapper"&gt;   &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;     &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;interface&lt;/span&gt; IValueProvider&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;bool&lt;/span&gt; ContainsPrefix(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; prefix);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;     ValueProviderResult GetValue(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; key);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt; }&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;IValueProvider的GetValue返回的是一个&lt;a title="ValueProviderResult Class" href="http://msdn2.microsoft.com/dd470160.aspx"&gt;ValueProviderResult&lt;/a&gt;对象，我们可以将ValueProviderResult看成是对ValueProvider提供对象的封装。如下面的代码片断所示，ValueProviderResult具有三个只读属性，其中RawValue表示原始的值对象。而AttemptedValue表示以值对象的字符串表示，该属性主要用于显示。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; [Serializable]&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; ValueProviderResult&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt; {    &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; ValueProviderResult(&lt;span style="color: #0000ff"&gt;object&lt;/span&gt; rawValue, &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; attemptedValue, CultureInfo culture);    &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;object&lt;/span&gt; ConvertTo(Type type);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;virtual&lt;/span&gt; &lt;span style="color: #0000ff"&gt;object&lt;/span&gt; ConvertTo(Type type, CultureInfo culture);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt;  &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; AttemptedValue { get; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; CultureInfo Culture { get; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum10"&gt;  10:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;object&lt;/span&gt; RawValue { get; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum11"&gt;  11:&lt;/span&gt; }&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;ValueProviderResult提供了两个ConvertTo方法重载以实现向指定目标类型的转换。某些类型的格式化行为依赖于相应的语言文化（比如时间、日期和货币等），而这个辅助格式湖的语言文化信息通过Culture属性表示。其中第一个ValueProviderResult方法重载通过属性Culture表示的语言文化进行类型转化。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;font size="4"&gt;&lt;font style="font-weight: bold"&gt;二、NameValueCollectionValueProvider&lt;/font&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;前面已经说过，Model数据源一般具有类似于字典的结构，而NameValueCollection可以表示为Key不具有唯一性的字典，将NameValueCollection对象作为数据源的ValueProvider通过具有如下定义的&lt;a title="NameValueCollectionValueProvider Class" href="http://msdn2.microsoft.com/ee703470.aspx"&gt;NameValueCollectionValueProvider&lt;/a&gt;类型表示。表示数据源的NameValueCollection对象在构造函数中指定，构造函数的另一个CultureInfo类型的参数表示服务于数据转换的语言文化信息。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; NameValueCollectionValueProvider : IUnvalidatedValueProvider, IEnumerableValueProvider, IValueProvider&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {   &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color: #008000"&gt;//其他成员&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; NameValueCollectionValueProvider(NameValueCollection collection,  CultureInfo culture);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;  &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;virtual&lt;/span&gt; &lt;span style="color: #0000ff"&gt;bool&lt;/span&gt; ContainsPrefix(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; prefix);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;virtual&lt;/span&gt; IDictionary&amp;lt;&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;string&lt;/span&gt;&amp;gt; GetKeysFromPrefix(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; prefix);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;virtual&lt;/span&gt; ValueProviderResult GetValue(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; key);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;virtual&lt;/span&gt; ValueProviderResult GetValue(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; key, &lt;span style="color: #0000ff"&gt;bool&lt;/span&gt; skipValidation);  &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum10"&gt;  10:&lt;/span&gt; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum11"&gt;  11:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum12"&gt;  12:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;interface&lt;/span&gt; IEnumerableValueProvider : IValueProvider&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum13"&gt;  13:&lt;/span&gt; {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum14"&gt;  14:&lt;/span&gt;     IDictionary&amp;lt;&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;, &lt;span style="color: #0000ff"&gt;string&lt;/span&gt;&amp;gt; GetKeysFromPrefix(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; prefix);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum15"&gt;  15:&lt;/span&gt; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum16"&gt;  16:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum17"&gt;  17:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;interface&lt;/span&gt; IUnvalidatedValueProvider : IValueProvider&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum18"&gt;  18:&lt;/span&gt; {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum19"&gt;  19:&lt;/span&gt;     ValueProviderResult GetValue(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; key, &lt;span style="color: #0000ff"&gt;bool&lt;/span&gt; skipValidation);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum20"&gt;  20:&lt;/span&gt; }&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;从上面的代码片断我们可以看到，除了IValueProvider接口，NameValueCollectionValueProvider还实现了IEnumerableValueProvider和IUnvalidatedValueProvider两个接口。顾名思义，IEnumerableValueProvider主要用于针对目标类型为集合的数据提供，方法GetKeysFromPrefix以一字典的形式返回具有指定前缀的Key。在默认的情况下，在进行数据提供的同时会对数据进行验证，而IUnvalidatedValueProvider接口提供了一个额外的GetValue方法是我们可以忽略对数据的验证。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;font size="4"&gt;&lt;font style="font-weight: bold"&gt;三、两种前缀形式&lt;/font&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;辅助实现Model绑定的数据提供机制是以Model元数据为基础的，通过《&lt;a href="http://www.cnblogs.com/artech/archive/2012/04/11/model-metadata-01.html"&gt;初识Model元数据&lt;/a&gt;》我们知道用于描述一个复杂数据类型的Model元数据具有一个树型的层次化结构，而作为数据源的NameValueCollection却是一个“扁平”的结构，两者之前的匹配通过前缀来表示。举个简单的例子，假设通过NameValueCollectionValueProvider提供对象的目标类型为具有如下定义的Contact。表示联系地址的属性是一个复杂类型Address，所以针对Contact类型的Model元数据树具有两个层级。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; Contact&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; Name { get; set; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; PhoneNo { get; set; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; EmailAddress { get; set; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; Address Address { get; set; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; Address&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt; {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum10"&gt;  10:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; Province { get; set; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum11"&gt;  11:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; City { get; set; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum12"&gt;  12:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; District { get; set; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum13"&gt;  13:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; Street { get; set; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum14"&gt;  14:&lt;/span&gt; }&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;由于NameValueCollection中每个元数据的值都是一个字符串，所以不可能单独表示一个复杂类型，复杂类型对象需要通过多个元素值组装而成。如果通过NameValueCollectionValueProvider来初始化一个完整的Contact对象，表示数据源的NameValueCollection至少需要包含7个元素，分别针对Contact除Address属性的三个属性值和作为Address的四个属性值，两类元素在NameValueCollection中通过基于属性的前缀来区分，具体的结构如下所示。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; Name:Foo&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; PhoneNo:123456789&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt; EmailAddress:Foomail.com&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt; Address.Province: 江苏&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt; Address.City: 苏州&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt; Address.District: 工业园区&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt; Address.Street: 星湖街328号&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;将点号(.)作为分隔符的前缀除了表示基于属性的层级关系之外，还可以用于数据筛选。如下面的代码片断所示，我们在ContactController中定义了一个用于添加联系人的AddContacts，它具有两个Contact类型的参数foo和bar，表示添加的两个不同的联系人。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; ContactController&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; AddContacts(Contact foo, Contact bar)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;     { &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;         &lt;span style="color: #008000"&gt;//省略实现&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt; }&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;如果我们采用NameValueCollectionValueProvider来提供作为AddContacts方法参数的两个Contact对象，保存在NameValueCollection的数据元素必须能够与它们进行合理映射。一般情况下这可以通过针对参数名的前缀来实现，具体数据结构如下所示。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; foo.Name：Foo&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; foo.PhoneNo：123456789&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt; foo.EmailAddress：Foo@gmail.com&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt; foo.Address.Province: 江苏&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt; foo.Address.City: 苏州&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt; foo.Address.District: 工业园区&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt; foo.Address.Street: 星湖街328号&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt; bar.Name：Bar&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum10"&gt;  10:&lt;/span&gt; bar.PhoneNo：987654321&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum11"&gt;  11:&lt;/span&gt; bar.EmailAddress：Bar@gmail.com&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum12"&gt;  12:&lt;/span&gt; bar.Address.Province: 江苏&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum13"&gt;  13:&lt;/span&gt; bar.Address.City: 苏州&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum14"&gt;  14:&lt;/span&gt; bar.Address.District: 工业园区&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum15"&gt;  15:&lt;/span&gt; bar.Address.Street: 机场路328号&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;除了采用基于“.”的前缀之外，数组或者集合类型的数据源元素可以采用基于“索引”的前缀，这样的前缀通过方括号“[]”表示，如下的数据结构就可以表示包含两个元素的Contact数组或者集合。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; [0].Name：Foo&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; [0].PhoneNo：123456789&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt; [0].EmailAddress：Foo@gmail.com&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt; ...&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt; [1].Name：Bar&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt; [1].PhoneNo：987654321&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt; [1].EmailAddress：Bar@gmail.com&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt; ...&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;除了采用数字作为索引之前，我们还可以按照如下的方式通过文字作为索引。针对两种不同形式的索引的Model绑定机制有所不同，我们会在后续的部分予以讲述。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; [foo].Name：Foo&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; [foo].PhoneNo：123456789&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt; [foo].EmailAddress：Foo@gmail.com&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt; ...&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt; [bar].Name：Bar&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt; [bar].PhoneNo：987654321&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt; [bar].EmailAddress：Bar@gmail.com&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt; ...&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;如果数据源元素针对不同的目标集合对象，同样需要采用相应的前缀予以区分，相面的数据结构可以看成是针对两个Contact列表（first和second）的数据源。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; first[0].Name：Zhao&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; first[0].PhoneNo：12&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt; first[0].EmailAddress：zhao @gmail.com&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt; ...&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt; first[1].Name：Qian&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt; first[1].PhoneNo：34&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt; first[1].EmailAddress：qian@gmail.com&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt; ...&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum10"&gt;  10:&lt;/span&gt; second[0].Name：Sun&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum11"&gt;  11:&lt;/span&gt; second[0].PhoneNo：56&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum12"&gt;  12:&lt;/span&gt; second[0].EmailAddress：sun@gmail.com&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum13"&gt;  13:&lt;/span&gt; ...&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum14"&gt;  14:&lt;/span&gt; second[1].Name：Li&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum15"&gt;  15:&lt;/span&gt; second[1].PhoneNo：78&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum16"&gt;  16:&lt;/span&gt; second[1].EmailAddress：li@gmail.com&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;&lt;strong&gt;&lt;font size="4"&gt;&lt;font style="font-weight: bold"&gt;四、实例演示：返回指定前缀的Key&lt;/font&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;在了解两种不同类型的前缀之后，我们来关注一下NameValueCollectionValueProvider实现的GetKeysFromPrefix方法。从该方法的定义可以看出它返回的是一个IDictionary&amp;lt;string, string&amp;gt;对象，但是这个对象具有怎样的数据呢？我们为此来进行一个实例演示。在通过Visual Studio的ASP.NET MVC项目模板创建的空Web应用中，我们定义了如下一个默认的HomeController。在Action方法Index中我们创建了一个NameValueCollection对象，并针对它创建一个NameValueCollectionValueProvider．&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; HomeController : Controller&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; Index()&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;         NameValueCollection datasource = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; NameValueCollection();&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;         datasource.Add(&lt;span style="color: #006080"&gt;&amp;quot;foo.Name&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;Foo&amp;quot;&lt;/span&gt;);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt;         datasource.Add(&lt;span style="color: #006080"&gt;&amp;quot;foo.PhoneNo&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;123456789&amp;quot;&lt;/span&gt;);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt;         datasource.Add(&lt;span style="color: #006080"&gt;&amp;quot;foo.EmailAddress&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;Foo@gmail.com&amp;quot;&lt;/span&gt;);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt;         datasource.Add(&lt;span style="color: #006080"&gt;&amp;quot;foo.Address.Province&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;江苏&amp;quot;&lt;/span&gt;);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum10"&gt;  10:&lt;/span&gt;         datasource.Add(&lt;span style="color: #006080"&gt;&amp;quot;foo.Address.City&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;苏州&amp;quot;&lt;/span&gt;);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum11"&gt;  11:&lt;/span&gt;         datasource.Add(&lt;span style="color: #006080"&gt;&amp;quot;foo.Address.District&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;工业园区&amp;quot;&lt;/span&gt;);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum12"&gt;  12:&lt;/span&gt;         datasource.Add(&lt;span style="color: #006080"&gt;&amp;quot;foo.Address.Street&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;星湖街328号&amp;quot;&lt;/span&gt;);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum13"&gt;  13:&lt;/span&gt;         NameValueCollectionValueProvider valueProvider = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; NameValueCollectionValueProvider(datasource, CultureInfo.InvariantCulture);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum14"&gt;  14:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum15"&gt;  15:&lt;/span&gt;         var keyDictionary = valueProvider.GetKeysFromPrefix(&lt;span style="color: #006080"&gt;&amp;quot;foo&amp;quot;&lt;/span&gt;);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum16"&gt;  16:&lt;/span&gt;         Response.Write(&lt;span style="color: #006080"&gt;&amp;quot;foo&amp;lt;br/&amp;gt;&amp;quot;&lt;/span&gt;);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum17"&gt;  17:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;foreach&lt;/span&gt; (var item &lt;span style="color: #0000ff"&gt;in&lt;/span&gt; keyDictionary)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum18"&gt;  18:&lt;/span&gt;         {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum19"&gt;  19:&lt;/span&gt;             Response.Write(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;.Format(&lt;span style="color: #006080"&gt;&amp;quot;{0}: {1}&amp;lt;br/&amp;gt;&amp;quot;&lt;/span&gt;, item.Key, item.Value));&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum20"&gt;  20:&lt;/span&gt;         }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum21"&gt;  21:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum22"&gt;  22:&lt;/span&gt;         keyDictionary = valueProvider.GetKeysFromPrefix(&lt;span style="color: #006080"&gt;&amp;quot;foo.Address&amp;quot;&lt;/span&gt;);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum23"&gt;  23:&lt;/span&gt;         Response.Write(&lt;span style="color: #006080"&gt;&amp;quot;&amp;lt;br/&amp;gt;foo.Address&amp;lt;br/&amp;gt;&amp;quot;&lt;/span&gt;);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum24"&gt;  24:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;foreach&lt;/span&gt; (var item &lt;span style="color: #0000ff"&gt;in&lt;/span&gt; keyDictionary)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum25"&gt;  25:&lt;/span&gt;         {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum26"&gt;  26:&lt;/span&gt;             Response.Write(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;.Format(&lt;span style="color: #006080"&gt;&amp;quot;{0}: {1}&amp;lt;br/&amp;gt;&amp;quot;&lt;/span&gt;, item.Key, item.Value));&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum27"&gt;  27:&lt;/span&gt;         }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum28"&gt;  28:&lt;/span&gt;     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum29"&gt;  29:&lt;/span&gt; }&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;通过上面的代码片断可以看出，作为NameValueCollectionValueProvider的数据元素是按照Contact类型的属性定义来添加的。我们分别将“foo”和“foo.Address”作为前缀返回以此作为前缀的Key。运行该程序后会在浏览器上得到如下的输出结果。我们可以看到对于针对指定前缀返回的字典对象，其Key和Value的不同之处在于前者没有包含指定的前缀而后者包含。此外，字典对象包含的元素全部处于同一级别，将“foo”指定为前缀时返回的元素针对于Contact的四个属性。虽然NameValueCollection中并不包含一个名为“foo.Address”的元素，但是依然会将其单独作为以“foo”为前缀的Key。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; foo&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; Name            : foo.Name&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt; PhoneNo         : foo.PhoneNo&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt; EmailAddress    : foo.EmailAddress&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt; Address         : foo.Address&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt; foo.Address&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt; Province        : foo.Address.Province&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt; City            : foo.Address.City&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum10"&gt;  10:&lt;/span&gt; District        : foo.Address.District&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum11"&gt;  11:&lt;/span&gt; Street          : foo.Address.Street&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;接下来我们采用相应的方式来演示基于索引的前缀，为此我们将HomeController的Index反方法进行了如下的改写。作为数据源的NameValueCollection对象针对一个包含两个元素的Contact集合，前缀“first”可以作为集合对象的名称。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; HomeController : Controller&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; Index()&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;         NameValueCollection datasource = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; NameValueCollection();&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;         datasource.Add(&lt;span style="color: #006080"&gt;&amp;quot;first[0].Name&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;Foo&amp;quot;&lt;/span&gt;);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt;         datasource.Add(&lt;span style="color: #006080"&gt;&amp;quot;first[0].PhoneNo&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;123456789&amp;quot;&lt;/span&gt;);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt;         datasource.Add(&lt;span style="color: #006080"&gt;&amp;quot;first[0].EmailAddress&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;Foo@gmail.com&amp;quot;&lt;/span&gt;);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum10"&gt;  10:&lt;/span&gt;         datasource.Add(&lt;span style="color: #006080"&gt;&amp;quot;first[1].Name&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;Bar&amp;quot;&lt;/span&gt;);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum11"&gt;  11:&lt;/span&gt;         datasource.Add(&lt;span style="color: #006080"&gt;&amp;quot;first[1].PhoneNo&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;987654321&amp;quot;&lt;/span&gt;);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum12"&gt;  12:&lt;/span&gt;         datasource.Add(&lt;span style="color: #006080"&gt;&amp;quot;first[1].EmailAddress&amp;quot;&lt;/span&gt;, &lt;span style="color: #006080"&gt;&amp;quot;Bar@gmail.com&amp;quot;&lt;/span&gt;);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum13"&gt;  13:&lt;/span&gt;         NameValueCollectionValueProvider valueProvider = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; NameValueCollectionValueProvider(datasource, CultureInfo.InvariantCulture);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum14"&gt;  14:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum15"&gt;  15:&lt;/span&gt;         var keyDictionary = valueProvider.GetKeysFromPrefix(&lt;span style="color: #006080"&gt;&amp;quot;first&amp;quot;&lt;/span&gt;);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum16"&gt;  16:&lt;/span&gt;         Response.Write(&lt;span style="color: #006080"&gt;&amp;quot;first&amp;lt;br/&amp;gt;&amp;quot;&lt;/span&gt;);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum17"&gt;  17:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;foreach&lt;/span&gt; (var item &lt;span style="color: #0000ff"&gt;in&lt;/span&gt; keyDictionary)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum18"&gt;  18:&lt;/span&gt;         {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum19"&gt;  19:&lt;/span&gt;             Response.Write(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;.Format(&lt;span style="color: #006080"&gt;&amp;quot;{0}: {1}&amp;lt;br/&amp;gt;&amp;quot;&lt;/span&gt;, item.Key, item.Value));&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum20"&gt;  20:&lt;/span&gt;         }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum21"&gt;  21:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum22"&gt;  22:&lt;/span&gt;         keyDictionary = valueProvider.GetKeysFromPrefix(&lt;span style="color: #006080"&gt;&amp;quot;first[0]&amp;quot;&lt;/span&gt;);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum23"&gt;  23:&lt;/span&gt;         Response.Write(&lt;span style="color: #006080"&gt;&amp;quot;&amp;lt;br/&amp;gt;first[0]&amp;lt;br/&amp;gt;&amp;quot;&lt;/span&gt;);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum24"&gt;  24:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;foreach&lt;/span&gt; (var item &lt;span style="color: #0000ff"&gt;in&lt;/span&gt; keyDictionary)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum25"&gt;  25:&lt;/span&gt;         {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum26"&gt;  26:&lt;/span&gt;             Response.Write(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;.Format(&lt;span style="color: #006080"&gt;&amp;quot;{0}: {1}&amp;lt;br/&amp;gt;&amp;quot;&lt;/span&gt;, item.Key, item.Value));&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum27"&gt;  27:&lt;/span&gt;         }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum28"&gt;  28:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum29"&gt;  29:&lt;/span&gt;         keyDictionary = valueProvider.GetKeysFromPrefix(&lt;span style="color: #006080"&gt;&amp;quot;first[1]&amp;quot;&lt;/span&gt;);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum30"&gt;  30:&lt;/span&gt;         Response.Write(&lt;span style="color: #006080"&gt;&amp;quot;&amp;lt;br/&amp;gt;first[1]&amp;lt;br/&amp;gt;&amp;quot;&lt;/span&gt;);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum31"&gt;  31:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;foreach&lt;/span&gt; (var item &lt;span style="color: #0000ff"&gt;in&lt;/span&gt; keyDictionary)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum32"&gt;  32:&lt;/span&gt;         {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum33"&gt;  33:&lt;/span&gt;             Response.Write(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;.Format(&lt;span style="color: #006080"&gt;&amp;quot;{0}: {1}&amp;lt;br/&amp;gt;&amp;quot;&lt;/span&gt;, item.Key, item.Value));&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum34"&gt;  34:&lt;/span&gt;         }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum35"&gt;  35:&lt;/span&gt;     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum36"&gt;  36:&lt;/span&gt; }&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;我们分别针对三个前缀“first”、“first[0]”和“first[1]”获取相应字典对象并将其Key和Value呈现出来。该程序执行之后会在浏览器中产生如下的输出，如果我们将“[”和“]”视为和”.”一样的分割符，GetKeysFromPrefix针对索引作为前缀的规则与基于“.”前缀的规则没有本质的区别。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; first&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; 0: first[0]&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt; 1: first[1]&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt; first[0]&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt; Name        : first[0].Name&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt; PhoneNo     : first[0].PhoneNo&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt; EmailAddress: first[0].EmailAddress&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum10"&gt;  10:&lt;/span&gt; first[1]&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum11"&gt;  11:&lt;/span&gt; Name        : first[1].Name&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum12"&gt;  12:&lt;/span&gt; PhoneNo     : first[1].PhoneNo&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum13"&gt;  13:&lt;/span&gt; EmailAddress: first[1].EmailAddress&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;&lt;strong&gt;&lt;font size="4"&gt;&lt;font style="font-weight: bold"&gt;五、FormValueProvider与QueryStringValueProvider&lt;/font&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;在ASP.NET MVC 应用编程接口中，NameValueCollectionValueProvider具有两个继承者，即&lt;a title="FormValueProvider Class" href="http://msdn2.microsoft.com/ee703584.aspx"&gt;FormValueProvider&lt;/a&gt;和&lt;a title="QueryStringValueProvider Class" href="http://msdn2.microsoft.com/ee703598.aspx"&gt;QueryStringValueProvider&lt;/a&gt;。对于FormValueProvider来说，最终作为数据源的NameValueCollection对象通过请求表单创建，Name和Value分别来源于表单元素的名称和值，它的定义基本上可以通过如下的代码表示（实际定义有所差异）。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;sealed&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; FormValueProvider : NameValueCollectionValueProvider&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; FormValueProvider(ControllerContext controllerContext)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;         : &lt;span style="color: #0000ff"&gt;base&lt;/span&gt;(controllerContext.RequestContext.HttpContext.Request.Form, CultureInfo.CurrentCulture)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;     { }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt; }&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;对于QueryStringValueProvider来说，无须多说，其作为数据源的NameValueCollection对象爱那个自然来源于请求的查询字符串，其定义基本上可以通过如下的代码表示（实际定义有所差异）。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;sealed&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; QueryStringValueProvider: NameValueCollectionValueProvider&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; NameValueCollection(ControllerContext controllerContext)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;         : &lt;span style="color: #0000ff"&gt;base&lt;/span&gt;(controllerContext.RequestContext.HttpContext.Request.QueryString, CultureInfo.CurrentCulture)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;     { }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt; }&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&amp;#160;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/artech/archive/2012/05/17/value-provider-01.html"&gt;ASP.NET MVC以ValueProvider为核心的值提供系统: NameValueCollectionValueProvider&lt;/a&gt;   &lt;br /&gt;&lt;a href="http://www.cnblogs.com/artech/archive/2012/05/18/value-provider-02.html"&gt;ASP.NET MVC以ValueProvider为核心的值提供系统: DictionaryValueProvider&lt;/a&gt;   &lt;br /&gt;&lt;a href="http://www.cnblogs.com/artech/archive/2012/05/19/value-provider-03.html"&gt;ASP.NET MVC以ValueProvider为核心的值提供系统: ValueProviderFactory&lt;/a&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/artech/aggbug/2505707.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/artech/archive/2012/05/17/value-provider-01.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/artech/archive/2012/05/15/custom-client-validation.html</id><title type="text">ASP.NET MVC如何实现自定义验证（服务端验证+客户端验证）</title><summary type="text">ASP.NET MVC通过Model验证帮助我们很容易的实现对数据的验证。对于自定义验证，我们也只需要定义相应的Validation就可以了，不过服务端验证比较简单，而客户端验证就要稍微复杂一些，本文提供一个简单的实例说明在ASP.NET MVC中实现自定义验证的基本步骤。</summary><published>2012-05-15T10:37:00Z</published><updated>2012-05-15T10:37:00Z</updated><author><name>Artech</name><uri>http://www.cnblogs.com/artech/</uri></author><link rel="alternate" href="http://www.cnblogs.com/artech/archive/2012/05/15/custom-client-validation.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/artech/archive/2012/05/15/custom-client-validation.html"/><content type="html">&lt;p&gt;ASP.NET MVC通过Model验证帮助我们很容易的实现对数据的验证，在默认的情况下，基于ValidationAttribute的声明是验证被使用，我们只需要将相应的ValidationAttribute应用到Model的类型或者属性上即可。对于自定义验证，我们也只需要定义相应的Validation就可以了，不过服务端验证比较简单，而客户端验证就要稍微复杂一些，本文提供一个简单的实例说明在ASP.NET MVC中实现自定义验证的基本步骤。[源代码从&lt;a href="http://files.cnblogs.com/artech/CustomClientValidation.rar"&gt;这里&lt;/a&gt;下载]&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font style="font-weight: bold" size="4"&gt;一、AgeRangeAttribute &lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;用于验证出生日期字段以确保年龄在制定的范围之内的AgeRangeAttribute定义如下，简单起见，我们直接让它直接继承自RangeAttribute。服务端验证逻辑定义在重写的IsValid方法中，并且重写了FormatErrorMessage方法以便生成针对年龄的验证消息。AgeRangeAttribute实现了IClientValidatable接口，并在实现的GetClientValidationRules方法中生成客户端验证规则。在生成的类型为&amp;#8220;agerange&amp;#8221;的ModelClientValidationRule 对象中包含三个参数（currentdate、minage和maxage），分别表示当前日期（用于计算年龄）、允许年龄的范围。&lt;/p&gt;  &lt;div id="codeSnippetWrapper"&gt;   &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;     &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; AgeRangeAttribute : RangeAttribute, IClientValidatable&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; AgeRangeAttribute(&lt;span style="color: #0000ff"&gt;int&lt;/span&gt; minimum, &lt;span style="color: #0000ff"&gt;int&lt;/span&gt; maximum)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;         : &lt;span style="color: #0000ff"&gt;base&lt;/span&gt;(minimum, maximum)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;     { }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;&amp;nbsp; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;override&lt;/span&gt; &lt;span style="color: #0000ff"&gt;bool&lt;/span&gt; IsValid(&lt;span style="color: #0000ff"&gt;object&lt;/span&gt; &lt;span style="color: #0000ff"&gt;value&lt;/span&gt;)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt;     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt;         DateTime birthDate = (DateTime)&lt;span style="color: #0000ff"&gt;value&lt;/span&gt;;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum10"&gt;  10:&lt;/span&gt;         DateTime age = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; DateTime(DateTime.Now.Ticks - birthDate.Ticks);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum11"&gt;  11:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; age.Year &amp;gt;= (&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;)&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.Minimum &amp;amp;&amp;amp; age.Year &amp;lt;= (&lt;span style="color: #0000ff"&gt;int&lt;/span&gt;)&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.Maximum;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum12"&gt;  12:&lt;/span&gt;     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum13"&gt;  13:&lt;/span&gt;&amp;nbsp; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum14"&gt;  14:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;override&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; FormatErrorMessage(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; name)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum15"&gt;  15:&lt;/span&gt;     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum16"&gt;  16:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff"&gt;base&lt;/span&gt;.FormatErrorMessage(&lt;span style="color: #006080"&gt;"年龄"&lt;/span&gt;);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum17"&gt;  17:&lt;/span&gt;     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum18"&gt;  18:&lt;/span&gt;&amp;nbsp; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum19"&gt;  19:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; IEnumerable&amp;lt;ModelClientValidationRule&amp;gt; GetClientValidationRules(ModelMetadata metadata, ControllerContext context)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum20"&gt;  20:&lt;/span&gt;     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum21"&gt;  21:&lt;/span&gt;         ModelClientValidationRule validationRule = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; ModelClientValidationRule(){ ValidationType = &lt;span style="color: #006080"&gt;"agerange"&lt;/span&gt;, ErrorMessage= FormatErrorMessage(metadata.DisplayName)};&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum22"&gt;  22:&lt;/span&gt;         validationRule.ValidationParameters.Add(&lt;span style="color: #006080"&gt;"currentdate"&lt;/span&gt;,DateTime.Today.ToString(&lt;span style="color: #006080"&gt;"dd-MM-yyyy"&lt;/span&gt;));&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum23"&gt;  23:&lt;/span&gt;         validationRule.ValidationParameters.Add(&lt;span style="color: #006080"&gt;"minage"&lt;/span&gt;,&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.Minimum);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum24"&gt;  24:&lt;/span&gt;         validationRule.ValidationParameters.Add(&lt;span style="color: #006080"&gt;"maxage"&lt;/span&gt;,&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.Maximum);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum25"&gt;  25:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;yield&lt;/span&gt; &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; validationRule;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum26"&gt;  26:&lt;/span&gt;     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum27"&gt;  27:&lt;/span&gt; }&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;&lt;strong&gt;&lt;font size="4"&gt;&lt;font style="font-weight: bold"&gt;二、注册客户端验证方法&lt;/font&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;由于ASP.NET MVC采用JQuery Validation进行客户端验证，我们可以通过如下的这段javascript来注册用于实现客户端验证的function和添加相应的adapter。添加到jQuery.validator的用于进行年龄范围验证的function具有三个参数（value、element、params）分别表示被验证的值、元素和传入的参数。验证逻辑必须的三个数值（当前日期、年龄范围最小和最大值）通过参数params获得。而该参数实际上是在添加adapter时从通过上面定义的GetClientValidationRules方法生成的验证规则中获取的。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; jQuery.validator.addMethod(&lt;span style="color: #006080"&gt;"agerange"&lt;/span&gt;,&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;function&lt;/span&gt; (value, element, &lt;span style="color: #0000ff"&gt;params&lt;/span&gt;) {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;var&lt;/span&gt; minAge = &lt;span style="color: #0000ff"&gt;params&lt;/span&gt;.minage;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;var&lt;/span&gt; maxAge = &lt;span style="color: #0000ff"&gt;params&lt;/span&gt;.maxage;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;&amp;nbsp; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;var&lt;/span&gt; literalCurrentDate = &lt;span style="color: #0000ff"&gt;params&lt;/span&gt;.currentdate;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;var&lt;/span&gt; literalBirthDate = value;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;var&lt;/span&gt; literalCurrentDates = literalCurrentDate.split(&lt;span style="color: #006080"&gt;'-'&lt;/span&gt;);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum10"&gt;  10:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;var&lt;/span&gt; literalBirthDates = literalBirthDate.split(&lt;span style="color: #006080"&gt;'-'&lt;/span&gt;);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum11"&gt;  11:&lt;/span&gt;&amp;nbsp; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum12"&gt;  12:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;var&lt;/span&gt; birthDate = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Date(literalBirthDates[2], literalBirthDates[1], literalBirthDates[0]);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum13"&gt;  13:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;var&lt;/span&gt; currentDate = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Date(literalCurrentDates[2], literalCurrentDates[1], literalCurrentDates[0]);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum14"&gt;  14:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;var&lt;/span&gt; age = currentDate.getFullYear() - birthDate.getFullYear();&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum15"&gt;  15:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; age &amp;gt;= minAge &amp;amp;&amp;amp; age &amp;lt;= maxAge&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum16"&gt;  16:&lt;/span&gt; });&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum17"&gt;  17:&lt;/span&gt;&amp;nbsp; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum18"&gt;  18:&lt;/span&gt; jQuery.validator.unobtrusive.adapters.add(&lt;span style="color: #006080"&gt;"agerange"&lt;/span&gt;, [&lt;span style="color: #006080"&gt;"currentdate"&lt;/span&gt;, &lt;span style="color: #006080"&gt;"minage"&lt;/span&gt;, &lt;span style="color: #006080"&gt;"maxage"&lt;/span&gt;], &lt;span style="color: #0000ff"&gt;function&lt;/span&gt; (options) {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum19"&gt;  19:&lt;/span&gt;     options.rules[&lt;span style="color: #006080"&gt;"agerange"&lt;/span&gt;] = {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum20"&gt;  20:&lt;/span&gt;         currentdate: options.&lt;span style="color: #0000ff"&gt;params&lt;/span&gt;.currentdate,&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum21"&gt;  21:&lt;/span&gt;         minage: options.&lt;span style="color: #0000ff"&gt;params&lt;/span&gt;.minage,&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum22"&gt;  22:&lt;/span&gt;         maxage: options.&lt;span style="color: #0000ff"&gt;params&lt;/span&gt;.maxage&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum23"&gt;  23:&lt;/span&gt;     };&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum24"&gt;  24:&lt;/span&gt;     options.messages[&lt;span style="color: #006080"&gt;"agerange"&lt;/span&gt;] = options.message;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum25"&gt;  25:&lt;/span&gt; });&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;&lt;strong&gt;&lt;font size="4"&gt;&lt;font style="font-weight: bold"&gt;三、AgeRangeAttribute的应用&lt;/font&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;现在我们将AgeRangeAttribute 应用到一个简单的ASP.NET MVC应用中。在通过VS的ASP.NET MVC项目模板创建的空Web应用中，我们定义了如下一个简单的Person类型，我们定义的AgeRangeAttribute 应用到了表示出生日期的BirthDate上，并将允许的年龄上、下限设置为１８和３０。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; Person&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     [DisplayName(&lt;span style="color: #006080"&gt;"姓名"&lt;/span&gt;)]&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; Name { get; set; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;&amp;nbsp; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;     [AgeRange(18, 30, ErrorMessage = &lt;span style="color: #006080"&gt;"{0}必须在{1}和{2}之间！"&lt;/span&gt;)]   &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt;     [DisplayName(&lt;span style="color: #006080"&gt;"出生日期"&lt;/span&gt;)]&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt;     [DisplayFormat(ApplyFormatInEditMode = &lt;span style="color: #0000ff"&gt;true&lt;/span&gt;, DataFormatString = &lt;span style="color: #006080"&gt;"{0:dd-MM-yyyy}"&lt;/span&gt;)]&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; DateTime? BirthDate { get; set; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum10"&gt;  10:&lt;/span&gt; }&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;然后我们添加如下一个HomeController，在默认的Action方法Index中我们将创建的Person对象呈现在默认的View中。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; HomeController : Controller&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; ActionResult Index()&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; View(&lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Person{ BirthDate = DateTime.Today, Name = &lt;span style="color: #006080"&gt;"Foo"&lt;/span&gt;});&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt;     [HttpPost]&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; ActionResult Index(Person person)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt;     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum10"&gt;  10:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; View(person);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum11"&gt;  11:&lt;/span&gt;     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum12"&gt;  12:&lt;/span&gt; }&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;如下所示的代码片断代表了View的定义，我们直接调用HtmlHelper&amp;lt;TModel&amp;gt;的扩展方法EditorModel将作为Model的Person对象以编辑模式呈现在一个表单中。最后一点不要忘了在Layout文件中讲包含上述javascript片断的js文件包含进来。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; @model Person&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; @using (Html.BeginForm())&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt; {     &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;     @Html.EditorForModel()&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;input&lt;/span&gt; &lt;span style="color: #ff0000"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="submit"&lt;/span&gt; &lt;span style="color: #ff0000"&gt;value&lt;/span&gt;&lt;span style="color: #0000ff"&gt;="Save"&lt;/span&gt; &lt;span style="color: #0000ff"&gt;/&amp;gt;&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt; }&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;运行我们的程序，输入不合法出生日期并点击&amp;#8221;Save&amp;#8221;按钮提交表单（针对第一次客户端验证），客户端验证将会生效，具体效果如下图所示。&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/artech/201205/201205151837097088.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/artech/201205/201205151837106706.png" width="403" height="240" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/artech/aggbug/2502036.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/artech/archive/2012/05/15/custom-client-validation.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/artech/archive/2012/05/14/web-api-demo.html</id><title type="text">通过ASP.NET Web API + JQuery创建一个简单的Web应用</title><summary type="text">看了dudu的《HttpClient + ASP.NET Web API, WCF之外的另一个选择》一文，想起多很久之前体验ASP.NET Web API而创建的一个Demo，放着也是放着，姑且拿出来与大家分享。这是一个只涉及到简单CRUD操作的Web应用，业务逻辑以Web API的形式定义并以服务的形式发布出来，前台通过jQuery处理用户交互并调用后台服务。[源代码从这里下载]</summary><published>2012-05-13T23:50:00Z</published><updated>2012-05-13T23:50:00Z</updated><author><name>Artech</name><uri>http://www.cnblogs.com/artech/</uri></author><link rel="alternate" href="http://www.cnblogs.com/artech/archive/2012/05/14/web-api-demo.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/artech/archive/2012/05/14/web-api-demo.html"/><content type="html">&lt;p&gt;看了dudu的《&lt;a href="http://www.cnblogs.com/dudu/archive/2012/05/11/asp_net_webapi_httpclient.html"&gt;HttpClient + ASP.NET Web API, WCF之外的另一个选择&lt;/a&gt;》一文，想起多很久之前体现ASP.NET Web API而创建的一个Demo。这是一个只涉及到简单CRUD操作的Web应用，业务逻辑以Web API的形式定义并以服务的形式发布出来，前台通过jQuery处理用户交互并调用后台服务。[源代码从&lt;a href="http://files.cnblogs.com/artech/WebApiDemo.rar"&gt;这里&lt;/a&gt;下载]&lt;/p&gt;  &lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;   &lt;p&gt;目录      &lt;br /&gt;一、一个简单的基于CRUD       &lt;br /&gt;二、通过ASP.NET Web API提供服务       &lt;br /&gt;三、通过JQuery消费服务&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;strong&gt;&lt;font size="4"&gt;&lt;font style="font-weight: bold"&gt;一、一个简单的基于CRUD的Web应用&lt;/font&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;这个简单的Demo应用用于模拟“联系人管理”。当页面加载的时候，所有的联系人列表被列出来。在同一个页面中，我们可以添加一个新的联系人，也可以修改和删除现有联系人信息。整个应用唯一的页面在浏览器中的呈现效果如下图所示。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/artech/201205/201205140749333305.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/artech/201205/201205140749345747.png" width="483" height="184" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font size="4"&gt;&lt;font style="font-weight: bold"&gt;二、通过ASP.NET Web API提供服务&lt;/font&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;我们来简单介绍作为Web API形式发布的联系人管理服务的定义，先来看看用于表示联系人的Contact类型的定义。&lt;/p&gt;  &lt;div id="codeSnippetWrapper"&gt;   &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;     &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; Contact&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; Id { get; set; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; FirstName { get; set; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; LastName { get; set; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; PhoneNo { get; set; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; EmailAddress { get; set; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt; }&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;“联系人服务”以具有如下定义的ContactController的形式定义，它是ApiController的子类。简单起见，我们采用静态字段作为对联系人信息的存储。ContactController定义了Get、Put、Post和Delete用于进行对联系人的获取、添加、修改和删除操作。我想对Web API不了解的人会感概，为了什么采用常用的四个HTTP方法作为操作的名称，因为它们在默认的情况下就可以映射为HTTP请求的方法。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; ContactController : ApiController&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; List&amp;lt;Contact&amp;gt; contacts = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; List&amp;lt;Contact&amp;gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Contact{ Id=&lt;span style="color: #006080"&gt;&amp;quot;001&amp;quot;&lt;/span&gt;, FirstName = &lt;span style="color: #006080"&gt;&amp;quot;San&amp;quot;&lt;/span&gt;, LastName=&lt;span style="color: #006080"&gt;&amp;quot;Zhang&amp;quot;&lt;/span&gt;, PhoneNo=&lt;span style="color: #006080"&gt;&amp;quot;123&amp;quot;&lt;/span&gt;, EmailAddress=&lt;span style="color: #006080"&gt;&amp;quot;zhangsan@gmail.com&amp;quot;&lt;/span&gt;},&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Contact{ Id=&lt;span style="color: #006080"&gt;&amp;quot;002&amp;quot;&lt;/span&gt;,FirstName = &lt;span style="color: #006080"&gt;&amp;quot;Si&amp;quot;&lt;/span&gt;, LastName=&lt;span style="color: #006080"&gt;&amp;quot;Li&amp;quot;&lt;/span&gt;, PhoneNo=&lt;span style="color: #006080"&gt;&amp;quot;456&amp;quot;&lt;/span&gt;, EmailAddress=&lt;span style="color: #006080"&gt;&amp;quot;lisi@gmail.com&amp;quot;&lt;/span&gt;}&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt;     };&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt;         &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; IEnumerable&amp;lt;Contact&amp;gt; Get()&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum10"&gt;  10:&lt;/span&gt;     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum11"&gt;  11:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; contacts;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum12"&gt;  12:&lt;/span&gt;     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum13"&gt;  13:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum14"&gt;  14:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; Contact Get(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; id)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum15"&gt;  15:&lt;/span&gt;     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum16"&gt;  16:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; contacts.FirstOrDefault(c =&amp;gt; c.Id == id);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum17"&gt;  17:&lt;/span&gt;     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum18"&gt;  18:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum19"&gt;  19:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; Put(Contact contact)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum20"&gt;  20:&lt;/span&gt;     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum21"&gt;  21:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;if&lt;/span&gt; (&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;.IsNullOrEmpty(contact.Id))&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum22"&gt;  22:&lt;/span&gt;         {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum23"&gt;  23:&lt;/span&gt;             contact.Id = Guid.NewGuid().ToString();&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum24"&gt;  24:&lt;/span&gt;         }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum25"&gt;  25:&lt;/span&gt;         contacts.Add(contact);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum26"&gt;  26:&lt;/span&gt;     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum27"&gt;  27:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum28"&gt;  28:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; Post(Contact contact)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum29"&gt;  29:&lt;/span&gt;     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum30"&gt;  30:&lt;/span&gt;         Delete(contact.Id);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum31"&gt;  31:&lt;/span&gt;         contacts.Add(contact);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum32"&gt;  32:&lt;/span&gt;     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum33"&gt;  33:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum34"&gt;  34:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; Delete(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; id)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum35"&gt;  35:&lt;/span&gt;     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum36"&gt;  36:&lt;/span&gt;         Contact contact = contacts.FirstOrDefault(c =&amp;gt; c.Id == id);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum37"&gt;  37:&lt;/span&gt;         contacts.Remove(contact);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum38"&gt;  38:&lt;/span&gt;     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum39"&gt;  39:&lt;/span&gt; }&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;和ASP.NET MVC Web应用一样，我们同样采用URL路由机制来实现请求地址与目标Controller和Action的映射，而针对API默认注册的路有如下所示。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; MvcApplication : System.Web.HttpApplication&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color: #008000"&gt;//...&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;static&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; RegisterRoutes(RouteCollection routes)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;          &lt;span style="color: #008000"&gt;//...&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt;         routes.MapHttpRoute(&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt;             name: &lt;span style="color: #006080"&gt;&amp;quot;DefaultApi&amp;quot;&lt;/span&gt;,&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt;             routeTemplate: &lt;span style="color: #006080"&gt;&amp;quot;api/{controller}/{id}&amp;quot;&lt;/span&gt;,&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum10"&gt;  10:&lt;/span&gt;             defaults: &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; { id = RouteParameter.Optional }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum11"&gt;  11:&lt;/span&gt;         );&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum12"&gt;  12:&lt;/span&gt; }&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;按照注册的路由规则和Action方法名称与HTTP方法的默认影射机制，我们可以直接在浏览器中分别访问地址“/api/contact”和“/api/contact/001”得到所有联系人列表和ID为“001”的联系人信息。得到的结果如下图所示。&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/artech/201205/201205140749348189.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/artech/201205/201205140749355963.png" width="453" height="242" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;font size="4"&gt;&lt;font style="font-weight: bold"&gt;三、通过JQuery消费服务&lt;/font&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;我们通过ASP.NET MVC来构建Web应用，默认的HomeController定义如下，默认的Index操作仅仅是将默认的View呈现出来而已。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; HomeController : Controller&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; ActionResult Index()&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; View();&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt; }&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;View中对用户操作的相应和对后台服务的调用都通过JQuery来完成，整个View的定义如下所示。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;script&lt;/span&gt; &lt;span style="color: #ff0000"&gt;type&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;text/javascript&amp;quot;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: white; margin: 0em; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px"&gt;&lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt;     $(&lt;span style="color: #0000ff"&gt;function&lt;/span&gt; () {&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;         loadAllContacts();&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;        }&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;      )&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;function&lt;/span&gt; loadAllContacts() {&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt;         $.ajax({&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt;             url     : &lt;span style="color: #006080"&gt;&amp;quot;api/contact&amp;quot;&lt;/span&gt;,&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum10"&gt;  10:&lt;/span&gt;             type    : &lt;span style="color: #006080"&gt;&amp;quot;GET&amp;quot;&lt;/span&gt;,&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum11"&gt;  11:&lt;/span&gt;             dataType: &lt;span style="color: #006080"&gt;&amp;quot;json&amp;quot;&lt;/span&gt;,&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum12"&gt;  12:&lt;/span&gt;             success : &lt;span style="color: #0000ff"&gt;function&lt;/span&gt; (data) { renderContactList(data) }&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum13"&gt;  13:&lt;/span&gt;            }&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum14"&gt;  14:&lt;/span&gt;         );        &lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum15"&gt;  15:&lt;/span&gt;     }&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum16"&gt;  16:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum17"&gt;  17:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;function&lt;/span&gt; renderContactList(contacts) {&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum18"&gt;  18:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;var&lt;/span&gt; html = &lt;span style="color: #006080"&gt;&amp;quot;&amp;lt;table&amp;gt;&amp;quot;&lt;/span&gt;;&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum19"&gt;  19:&lt;/span&gt;         html += &lt;span style="color: #006080"&gt;&amp;quot;&amp;lt;tr&amp;gt;&amp;lt;th&amp;gt;First Name&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Last Name&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Phone No.&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;Email Address&amp;lt;/th&amp;gt;&amp;lt;th&amp;gt;&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;&amp;quot;&lt;/span&gt;;&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum20"&gt;  20:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;for&lt;/span&gt; (i = 0; i &amp;lt; contacts.length; i++) {&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum21"&gt;  21:&lt;/span&gt;             html += &lt;span style="color: #006080"&gt;&amp;quot;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;quot;&lt;/span&gt; + contacts[i].FirstName + &lt;span style="color: #006080"&gt;&amp;quot;&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&amp;quot;&lt;/span&gt;&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum22"&gt;  22:&lt;/span&gt;                  + contacts[i].LastName + &lt;span style="color: #006080"&gt;&amp;quot;&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&amp;quot;&lt;/span&gt; + contacts[i].PhoneNo + &lt;span style="color: #006080"&gt;&amp;quot;&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&amp;quot;&lt;/span&gt;&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum23"&gt;  23:&lt;/span&gt;                  + &lt;span style="color: #006080"&gt;&amp;quot;&amp;lt;input type=\&amp;quot;text\&amp;quot; class=\&amp;quot;textbox long\&amp;quot; id=\&amp;quot;&amp;quot;&lt;/span&gt; + contacts[i].Id + &lt;span style="color: #006080"&gt;&amp;quot;\&amp;quot; value =\&amp;quot;&amp;quot;&lt;/span&gt; + contacts[i].EmailAddress + &lt;span style="color: #006080"&gt;&amp;quot;\&amp;quot;/&amp;gt;&amp;quot;&lt;/span&gt; + &lt;span style="color: #006080"&gt;&amp;quot;&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&amp;quot;&lt;/span&gt;&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum24"&gt;  24:&lt;/span&gt;                  + &lt;span style="color: #006080"&gt;&amp;quot;&amp;lt;a href=\&amp;quot;#\&amp;quot; onclick = \&amp;quot;updateContact('&amp;quot;&lt;/span&gt; + contacts[i].Id + &lt;span style="color: #006080"&gt;&amp;quot;')\&amp;quot;&amp;gt;Update&amp;lt;/a&amp;gt; &amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;quot;&lt;/span&gt;&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum25"&gt;  25:&lt;/span&gt;                  + &lt;span style="color: #006080"&gt;&amp;quot;&amp;lt;a href=\&amp;quot;#\&amp;quot; onclick = \&amp;quot;deleteContact('&amp;quot;&lt;/span&gt; + contacts[i].Id + &lt;span style="color: #006080"&gt;&amp;quot;')\&amp;quot;&amp;gt;Delete&amp;lt;/a&amp;gt;&amp;quot;&lt;/span&gt; + &lt;span style="color: #006080"&gt;&amp;quot;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;quot;&lt;/span&gt;;&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum26"&gt;  26:&lt;/span&gt;         }&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum27"&gt;  27:&lt;/span&gt;         html += &lt;span style="color: #006080"&gt;&amp;quot;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;quot;&lt;/span&gt; + &lt;span style="color: #006080"&gt;&amp;quot;&amp;lt;input id=\&amp;quot;firstName\&amp;quot; type=\&amp;quot;text\&amp;quot; class=\&amp;quot;textbox\&amp;quot;/&amp;gt;&amp;quot;&lt;/span&gt; + &lt;span style="color: #006080"&gt;&amp;quot;&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&amp;quot;&lt;/span&gt;&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum28"&gt;  28:&lt;/span&gt;             + &lt;span style="color: #006080"&gt;&amp;quot;&amp;lt;input id=\&amp;quot;lastName\&amp;quot; type=\&amp;quot;text\&amp;quot; class=\&amp;quot;textbox\&amp;quot;/&amp;gt;&amp;quot;&lt;/span&gt; + &lt;span style="color: #006080"&gt;&amp;quot;&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&amp;quot;&lt;/span&gt;&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum29"&gt;  29:&lt;/span&gt;             + &lt;span style="color: #006080"&gt;&amp;quot;&amp;lt;input id=\&amp;quot;phoneNo\&amp;quot; type=\&amp;quot;text\&amp;quot; class=\&amp;quot;textbox\&amp;quot;/&amp;gt;&amp;quot;&lt;/span&gt; + &lt;span style="color: #006080"&gt;&amp;quot;&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&amp;quot;&lt;/span&gt;&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum30"&gt;  30:&lt;/span&gt;             + &lt;span style="color: #006080"&gt;&amp;quot;&amp;lt;input id=\&amp;quot;emailAddress\&amp;quot; type=\&amp;quot;text\&amp;quot; class=\&amp;quot;textbox long\&amp;quot;/&amp;gt;&amp;quot;&lt;/span&gt; + &lt;span style="color: #006080"&gt;&amp;quot;&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&amp;quot;&lt;/span&gt; &lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum31"&gt;  31:&lt;/span&gt;             + &lt;span style="color: #006080"&gt;&amp;quot;&amp;lt;a href=\&amp;quot;#\&amp;quot; id=\&amp;quot;add\&amp;quot; onclick=\&amp;quot;addContact();\&amp;quot;&amp;gt;Create&amp;lt;/a&amp;gt; &amp;quot;&lt;/span&gt; + &lt;span style="color: #006080"&gt;&amp;quot;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;quot;&lt;/span&gt;;&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum32"&gt;  32:&lt;/span&gt;         html += &lt;span style="color: #006080"&gt;&amp;quot;&amp;lt;/table&amp;gt;&amp;quot;&lt;/span&gt;;&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum33"&gt;  33:&lt;/span&gt;         $(&lt;span style="color: #006080"&gt;&amp;quot;#contacts&amp;quot;&lt;/span&gt;).html(html);&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum34"&gt;  34:&lt;/span&gt;         $(&lt;span style="color: #006080"&gt;&amp;quot;table tr:odd&amp;quot;&lt;/span&gt;).addClass(&lt;span style="color: #006080"&gt;&amp;quot;oddRow&amp;quot;&lt;/span&gt;);&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum35"&gt;  35:&lt;/span&gt;     }&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum36"&gt;  36:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum37"&gt;  37:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;function&lt;/span&gt; deleteContact(id) {&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum38"&gt;  38:&lt;/span&gt;         $.ajax({&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum39"&gt;  39:&lt;/span&gt;             url     : &lt;span style="color: #006080"&gt;&amp;quot;api/contact/&amp;quot;&lt;/span&gt; + id,&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum40"&gt;  40:&lt;/span&gt;             type    : &lt;span style="color: #006080"&gt;&amp;quot;DELETE&amp;quot;&lt;/span&gt;,&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum41"&gt;  41:&lt;/span&gt;             success : &lt;span style="color: #0000ff"&gt;function&lt;/span&gt; () { loadAllContacts();}&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum42"&gt;  42:&lt;/span&gt;         });&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum43"&gt;  43:&lt;/span&gt;     }&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum44"&gt;  44:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum45"&gt;  45:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;function&lt;/span&gt; updateContact(id) {&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum46"&gt;  46:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;var&lt;/span&gt; emailAddress = $(&lt;span style="color: #006080"&gt;&amp;quot;#&amp;quot;&lt;/span&gt; +id).attr(&lt;span style="color: #006080"&gt;&amp;quot;value&amp;quot;&lt;/span&gt;);&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum47"&gt;  47:&lt;/span&gt;         $.ajax({&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum48"&gt;  48:&lt;/span&gt;             url     : &lt;span style="color: #006080"&gt;&amp;quot;api/contact/&amp;quot;&lt;/span&gt; + id,&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum49"&gt;  49:&lt;/span&gt;             type    : &lt;span style="color: #006080"&gt;&amp;quot;GET&amp;quot;&lt;/span&gt;,&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum50"&gt;  50:&lt;/span&gt;             success : &lt;span style="color: #0000ff"&gt;function&lt;/span&gt; (contact) {&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum51"&gt;  51:&lt;/span&gt;                 contact.EmailAddress = emailAddress;&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum52"&gt;  52:&lt;/span&gt;                 update(contact);&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum53"&gt;  53:&lt;/span&gt;             }&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum54"&gt;  54:&lt;/span&gt;         });&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum55"&gt;  55:&lt;/span&gt;     }&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum56"&gt;  56:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum57"&gt;  57:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;function&lt;/span&gt; update(contact) {&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum58"&gt;  58:&lt;/span&gt;         $.ajax({&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum59"&gt;  59:&lt;/span&gt;             url         : &lt;span style="color: #006080"&gt;&amp;quot;api/contact/&amp;quot;&lt;/span&gt;,&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum60"&gt;  60:&lt;/span&gt;             type        : &lt;span style="color: #006080"&gt;&amp;quot;POST&amp;quot;&lt;/span&gt;,&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum61"&gt;  61:&lt;/span&gt;             data        : contact,&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum62"&gt;  62:&lt;/span&gt;             contentType : &lt;span style="color: #006080"&gt;&amp;quot;application/json&amp;quot;&lt;/span&gt;,&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum63"&gt;  63:&lt;/span&gt;             success     : &lt;span style="color: #0000ff"&gt;function&lt;/span&gt; () { loadAllContacts(); }&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum64"&gt;  64:&lt;/span&gt;         });&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum65"&gt;  65:&lt;/span&gt;     }&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum66"&gt;  66:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum67"&gt;  67:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;function&lt;/span&gt; addContact() {&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum68"&gt;  68:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;var&lt;/span&gt; contact = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Object();&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum69"&gt;  69:&lt;/span&gt;         contact.FirstName       = $(&lt;span style="color: #006080"&gt;&amp;quot;#firstName&amp;quot;&lt;/span&gt;).attr(&lt;span style="color: #006080"&gt;&amp;quot;value&amp;quot;&lt;/span&gt;);&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum70"&gt;  70:&lt;/span&gt;         contact.LastName        = $(&lt;span style="color: #006080"&gt;&amp;quot;#lastName&amp;quot;&lt;/span&gt;).attr(&lt;span style="color: #006080"&gt;&amp;quot;value&amp;quot;&lt;/span&gt;);&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum71"&gt;  71:&lt;/span&gt;         contact.PhoneNo         = $(&lt;span style="color: #006080"&gt;&amp;quot;#phoneNo&amp;quot;&lt;/span&gt;).attr(&lt;span style="color: #006080"&gt;&amp;quot;value&amp;quot;&lt;/span&gt;);&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum72"&gt;  72:&lt;/span&gt;         contact.EmailAddress    = $(&lt;span style="color: #006080"&gt;&amp;quot;#emailAddress&amp;quot;&lt;/span&gt;).attr(&lt;span style="color: #006080"&gt;&amp;quot;value&amp;quot;&lt;/span&gt;);&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum73"&gt;  73:&lt;/span&gt;         $.ajax({&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum74"&gt;  74:&lt;/span&gt;             url         : &lt;span style="color: #006080"&gt;&amp;quot;api/contact/&amp;quot;&lt;/span&gt;,&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum75"&gt;  75:&lt;/span&gt;             type        : &lt;span style="color: #006080"&gt;&amp;quot;PUT&amp;quot;&lt;/span&gt;,&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum76"&gt;  76:&lt;/span&gt;             data        : contact,&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum77"&gt;  77:&lt;/span&gt;             contentType : &lt;span style="color: #006080"&gt;&amp;quot;application/json&amp;quot;&lt;/span&gt;,&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum78"&gt;  78:&lt;/span&gt;             success     : &lt;span style="color: #0000ff"&gt;function&lt;/span&gt; () { loadAllContacts(); }&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum79"&gt;  79:&lt;/span&gt;         });&lt;!--CRLF--&gt;&lt;span style="color: #606060" id="lnum80"&gt;  80:&lt;/span&gt;     }&lt;!--CRLF--&gt;&lt;span style="color: #0000ff"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;script&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: #800000"&gt;div&lt;/span&gt; &lt;span style="color: #ff0000"&gt;id&lt;/span&gt;&lt;span style="color: #0000ff"&gt;=&amp;quot;contacts&amp;quot;&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span style="color: #800000"&gt;div&lt;/span&gt;&lt;span style="color: #0000ff"&gt;&amp;gt;&lt;/span&gt;&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;img src="http://www.cnblogs.com/artech/aggbug/2498806.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/artech/archive/2012/05/14/web-api-demo.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/artech/archive/2012/05/13/parameter-descriptor.html</id><title type="text">ASP.NET MVC三个重要的描述对象：ParameterDescriptor</title><summary type="text">Model绑定是为作为目标Action的方法准备参数列表的过程，所以针对参数的描述才是Model绑定的核心。在ASP.NET MVC应用编程接口中，服务于Model绑定的参数元数据通过ParameterDescriptor类型来表示，而ActionDescriptor的GetParameters方法返回的就是一个ParameterDescriptor数组。</summary><published>2012-05-13T10:37:00Z</published><updated>2012-05-13T10:37:00Z</updated><author><name>Artech</name><uri>http://www.cnblogs.com/artech/</uri></author><link rel="alternate" href="http://www.cnblogs.com/artech/archive/2012/05/13/parameter-descriptor.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/artech/archive/2012/05/13/parameter-descriptor.html"/><content type="html">&lt;p&gt;Model绑定是为作为目标Action的方法准备参数列表的过程，所以针对参数的描述才是Model绑定的核心。在ASP.NET MVC应用编程接口中，服务于Model绑定的参数元数据通过&lt;a title="ParameterDescriptor Class" href="http://msdn2.microsoft.com/dd470204.aspx"&gt;ParameterDescriptor&lt;/a&gt;类型来表示，而ActionDescriptor的GetParameters方法返回的就是一个ParameterDescriptor数组。&lt;/p&gt;  &lt;p&gt;如下面的代码片断所示，ParameterDescriptor同样实现了ICustomAttributeProvider接口提供应用在相应参数上的特性。ParameterDescriptor的只读属性ActionDescriptor表示描述所在Action方法的ActionDescriptor对象。属性ParameterName、ParameterType和DefaultValue分别表示参数的名称、类型和默认值。&lt;/p&gt;  &lt;div id="codeSnippetWrapper"&gt;   &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;     &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;abstract&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; ParameterDescriptor : ICustomAttributeProvider&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {   &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;virtual&lt;/span&gt; &lt;span style="color: #0000ff"&gt;object&lt;/span&gt;[] GetCustomAttributes(&lt;span style="color: #0000ff"&gt;bool&lt;/span&gt; inherit);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;virtual&lt;/span&gt; &lt;span style="color: #0000ff"&gt;object&lt;/span&gt;[] GetCustomAttributes(Type attributeType, &lt;span style="color: #0000ff"&gt;bool&lt;/span&gt; inherit);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;virtual&lt;/span&gt; &lt;span style="color: #0000ff"&gt;bool&lt;/span&gt; IsDefined(Type attributeType, &lt;span style="color: #0000ff"&gt;bool&lt;/span&gt; inherit);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;     &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;abstract&lt;/span&gt; ActionDescriptor ActionDescriptor { get; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;abstract&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; ParameterName { get; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;abstract&lt;/span&gt; Type ParameterType { get; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum10"&gt;  10:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;virtual&lt;/span&gt; &lt;span style="color: #0000ff"&gt;object&lt;/span&gt; DefaultValue { get; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum11"&gt;  11:&lt;/span&gt;&amp;nbsp; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum12"&gt;  12:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;virtual&lt;/span&gt; ParameterBindingInfo BindingInfo { get; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum13"&gt;  13:&lt;/span&gt; }&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;ParameterDescriptor的只读属性BindingInfo表示的System.Web.Mvc.ParameterBindingInfo对象封装一些信息用于控制请求数据与参数的绑定行为。如下面的代码片断所示，抽象类ParameterBindingInfo具有四个属性，其中类型为IModelBinder的Binder属性返回的ModelBinder对象是整个Model绑定的核心，我们将在本章后续部分进行单独介绍。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;abstract&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; ParameterBindingInfo&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;virtual&lt;/span&gt; IModelBinder Binder { get; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;     &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;virtual&lt;/span&gt; ICollection&amp;lt;&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;&amp;gt; Include { get; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;virtual&lt;/span&gt; ICollection&amp;lt;&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;&amp;gt; Exclude { get; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;virtual&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; Prefix { get; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt; }&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;如果参数类型是一个复杂类型，默认情况下会绑定其所有公共可读写属性，而两个ICollection&amp;lt;string&amp;gt;类型的属性Include和Exclude表示显示设置的参与/不参与绑定的属性名称列表。在默认情况下，请求数据与参数之间严格按照名称进行绑定，但是有时候请求数据名称具有相应的前缀，这个前缀体现在ParameterBindingInfo的Prefix属性上。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;ReflectedParameterDescriptor&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;原生的ParameterBindingInfo是通过针对表示参数的ParameterInfo进行反射获得，这样的ParameterBindingInfo通过&lt;a title="ReflectedParameterDescriptor Class" href="http://msdn2.microsoft.com/dd492734.aspx"&gt;ReflectedParameterDescriptor&lt;/a&gt;类型表示。如下面的代码片断所示，这个ParameterInfo对象通过只读属性ParameterInfo表示，并在构造函数中被初始化。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; ReflectedParameterDescriptor : ParameterDescriptor&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {   &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; ReflectedParameterDescriptor(ParameterInfo parameterInfo, ActionDescriptor actionDescriptor);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;override&lt;/span&gt; &lt;span style="color: #0000ff"&gt;object&lt;/span&gt;[] GetCustomAttributes(&lt;span style="color: #0000ff"&gt;bool&lt;/span&gt; inherit);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;override&lt;/span&gt; &lt;span style="color: #0000ff"&gt;object&lt;/span&gt;[] GetCustomAttributes(Type attributeType, &lt;span style="color: #0000ff"&gt;bool&lt;/span&gt; inherit);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;override&lt;/span&gt; &lt;span style="color: #0000ff"&gt;bool&lt;/span&gt; IsDefined(Type attributeType, &lt;span style="color: #0000ff"&gt;bool&lt;/span&gt; inherit);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt;     &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;override&lt;/span&gt; ActionDescriptor ActionDescriptor { get; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;override&lt;/span&gt; ParameterBindingInfo BindingInfo { get; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum10"&gt;  10:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;override&lt;/span&gt; &lt;span style="color: #0000ff"&gt;object&lt;/span&gt; DefaultValue { get; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum11"&gt;  11:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;override&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; ParameterName { get; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum12"&gt;  12:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;override&lt;/span&gt; Type ParameterType { get; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum13"&gt;  13:&lt;/span&gt;     &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum14"&gt;  14:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; ParameterInfo ParameterInfo { get; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum15"&gt;  15:&lt;/span&gt; }&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;ReflectedParameterDescriptor的BindingInfo属性返回的是一个ReflectedParameterBindingInfo对象，这是一个内部类型。该BindingInfo的Include、Exclude和Prefix属性来源于对应用在参数上的&lt;a title="BindAttribute Class" href="http://msdn2.microsoft.com/dd470613.aspx"&gt;BindAttribute&lt;/a&gt;特性的解析。如下面的代码片断所示，BindAttribute中同样定义了这三个属性，其中Include和Exclude为通过逗号作为分隔符的属性名称列表。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Class, AllowMultiple=&lt;span style="color: #0000ff"&gt;false&lt;/span&gt;, Inherited=&lt;span style="color: #0000ff"&gt;true&lt;/span&gt;)]&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;sealed&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; BindAttribute : Attribute&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt; {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;bool&lt;/span&gt; IsPropertyAllowed(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt; propertyName);   &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;     &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; Include { get; set; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; Exclude { get; set; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; Prefix { get; set;}&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt; }&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;布尔返回类型的IsPropertyAllowed方法用于判断指定的属性是否允许绑定，当指定在属性名在Include列表中（或者Include列表为空）并且不在Exclude列表的情况下返回True，否则返回False。&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/artech/archive/2012/05/10/controller-descriptor.html"&gt;ASP.NET MVC三个重要的描述对象：ControllerDescriptor&lt;/a&gt;  &lt;br /&gt;&lt;a href="http://www.cnblogs.com/artech/archive/2012/05/10/action-descriptor.html"&gt;ASP.NET MVC三个重要的描述对象：ActionDescriptor&lt;/a&gt;  &lt;br /&gt;&lt;a href="http://www.cnblogs.com/artech/archive/2012/05/11/controller-descriptor-and-action-descriptor-creation.html"&gt;ASP.NET MVC三个重要的描述对象：ControllerDescriptor与ActionDescriptor的创建机制&lt;/a&gt;  &lt;br /&gt;&lt;a href="http://www.cnblogs.com/artech/archive/2012/05/13/parameter-descriptor.html"&gt;ASP.NET MVC三个重要的描述对象：ParameterDescriptor&lt;/a&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/artech/aggbug/2498376.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/artech/archive/2012/05/13/parameter-descriptor.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/artech/archive/2012/05/12/wcf-book-sample-chapter.html</id><title type="text">《WCF全面解析》（上、下册）试读章节PDF下载</title><summary type="text">《WCF全面解析》在正式销售不到一周的时间内已经进入互动网7日销量已经进入计算机类书籍排名第2位，关注排名首位，谢谢各位的支持，现将三个试图章节共享出来与大家分享。</summary><published>2012-05-12T02:41:00Z</published><updated>2012-05-12T02:41:00Z</updated><author><name>Artech</name><uri>http://www.cnblogs.com/artech/</uri></author><link rel="alternate" href="http://www.cnblogs.com/artech/archive/2012/05/12/wcf-book-sample-chapter.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/artech/archive/2012/05/12/wcf-book-sample-chapter.html"/><content type="html">&lt;h1 align="left"&gt;&lt;a href="http://product.china-pub.com/199759"&gt;&lt;font size="4"&gt;&lt;font style="font-weight: bold"&gt;《WCF全面解析》（上册）&lt;/font&gt;&lt;/font&gt;&lt;/a&gt;&lt;font size="4"&gt;&lt;font style="font-weight: bold"&gt;第3章 绑定（Binding）&lt;/font&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p align="left"&gt;从整个基础构架的层次结构上讲，WCF可以分为服务模型层（Service Model Layer）和信道层（Channel Layer）两个层次。服务模型层建立在信道层之上，提供了一个统一的、可扩展的编程模型，而信道层通过信道栈（Channel Stack）实现对消息的传输和处理。作为终结点三要素之一的绑定在整个WCF架构体系中具有重要的地位。一方面，组成整个信道层的信道栈是由绑定创建的；另一方面，绑定又是连接两个层次的纽带。[PDF从&lt;a href="http://images.china-pub.com/ebook195001-200000/199759/ch03.pdf"&gt;这里&lt;/a&gt;下载]&lt;/p&gt;  &lt;p align="center"&gt;&lt;embed src="http://files.cnblogs.com/artech/ch03.pdf" width="600" height="300"&gt;&lt;/embed&gt; &lt;/p&gt;  &lt;h1 align="left"&gt;&lt;a href="http://product.china-pub.com/199759"&gt;&lt;font size="4"&gt;&lt;font style="font-weight: bold"&gt;《WCF全面解析》（上册）&lt;/font&gt;&lt;/font&gt;&lt;/a&gt;&lt;font size="4"&gt;&lt;font style="font-weight: bold"&gt;第6章 消息（Message）&lt;/font&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p align="left"&gt;虽然我们一直在强调WCF基于消息通信的本质，但是一般的编程人员却感受不到消息的存在，这是因为WCF设计的目标就是在内部实现消息通信的所有细节，并为最终的编程人员提供一个完全面向对象的应用编程接口。他们面对的是接口，却不知道服务契约对于服务的描述；面对的是数据类型，却不知道数据契约对序列化的作用；面对的是方法调用和返回值的获取，却不了解底层消息交换的过程。只有从消息交换层面来认识WCF才能洞悉其本质，也只有对整个消息处理流程具有清晰的认识才能创建高效的WCF应用。[PDF从&lt;a href="http://images.china-pub.com/ebook195001-200000/199759/ch06.pdf"&gt;这里&lt;/a&gt;下载]&lt;/p&gt;  &lt;p align="center"&gt;&lt;embed src="http://files.cnblogs.com/artech/ch06.pdf" width="600" height="300"&gt;&lt;/embed&gt; &lt;/p&gt;  &lt;h1 align="left"&gt;&lt;a href="http://product.china-pub.com/199759"&gt;&lt;font size="4"&gt;&lt;font style="font-weight: bold"&gt;《WCF全面解析》（下册）&lt;/font&gt;&lt;/font&gt;&lt;/a&gt;&lt;font size="4"&gt;&lt;font style="font-weight: bold"&gt;第5章 可靠会话（Reliable Sessions）&lt;/font&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;作为一个通信基础平台，WCF必须保证通信的可靠性。由于消息交换是WCF采用的通信手段，通信可靠性的保障体现在确保消息的可靠传输。WCF是一个消息处理框架，作为整个消息交换系统的两个终端，即发送端和接收端。WCF仅仅负责对消息的发送和接收，一旦消息通过WCF的信道层进入了网络，就脱离了WCF的控制范围。由于网络环境的限制，网络层不能百分之百地确保对消息的有效交付。如何克服中间环节的制约，确保从一端发送的消息能够被有效地交付给另一端，这就是可靠消息传输（Reliable Messaging）需要解决的问题。WCF通过可靠会话（Reliable Sessions）实现了端到端（End to End）的可靠消息传输。[PDF从&lt;a href="http://images.china-pub.com/ebook195001-200000/199759/ch05.pdf"&gt;这里&lt;/a&gt;下载]&lt;/p&gt;  &lt;p align="center"&gt;&lt;embed src="http://files.cnblogs.com/artech/ch05.pdf" width="600" height="300"&gt;&lt;/embed&gt; &lt;/p&gt;  &lt;hr /&gt;  &lt;p align="center"&gt;《WCF全面解析》在正式销售不到一周的时间内已经进入互动网7日销量已经进入计算机类书籍排名第2位，关注排名首位，谢谢各位的支持。&lt;/p&gt;  &lt;div style="padding-bottom: 0px; padding-left: 0px; width: 580px; padding-right: 0px; display: block; float: none; margin-left: auto; margin-right: auto; padding-top: 0px" id="scid:8747F07C-CDE8-481f-B0DF-C6CFD074BF67:8dbd185a-1ee3-4343-a651-82b146add648" class="wlWriterEditableSmartContent"&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/artech/201205/201205140756041790.png" title="" rel="thumbnail"&gt;&lt;img border="0" src="http://images.cnblogs.com/cnblogs_com/artech/201205/20120514075605329.png" width="580" height="508"  alt="" /&gt;&lt;/a&gt;&lt;/div&gt;  &lt;div style="padding-bottom: 0px; padding-left: 0px; width: 580px; padding-right: 0px; display: block; float: none; margin-left: auto; margin-right: auto; padding-top: 0px" id="scid:8747F07C-CDE8-481f-B0DF-C6CFD074BF67:1154fd76-fef5-4feb-a3a5-660fda763c03" class="wlWriterEditableSmartContent"&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/artech/201205/201205121041207666.png" title="" rel="thumbnail"&gt;&lt;img border="0" src="http://images.cnblogs.com/cnblogs_com/artech/201205/201205121041212235.png" width="580" height="498"  alt="" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;img src="http://www.cnblogs.com/artech/aggbug/2497064.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/artech/archive/2012/05/12/wcf-book-sample-chapter.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/artech/archive/2012/05/11/controller-descriptor-and-action-descriptor-creation.html</id><title type="text">ASP.NET MVC三个重要的描述对象：ControllerDescriptor和ActionDescriptor的创建</title><summary type="text">不论是用于描述Controller的ControllerDescriptor，还是用于描述Action方法的ActionDescriptor，都具有同步和异步两个版本，那么这些不同类型的ControllerDescriptor的ActionDescriptor是在什么情况下创建的呢？</summary><published>2012-05-11T00:52:00Z</published><updated>2012-05-11T00:52:00Z</updated><author><name>Artech</name><uri>http://www.cnblogs.com/artech/</uri></author><link rel="alternate" href="http://www.cnblogs.com/artech/archive/2012/05/11/controller-descriptor-and-action-descriptor-creation.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/artech/archive/2012/05/11/controller-descriptor-and-action-descriptor-creation.html"/><content type="html">&lt;p&gt;不论是用于描述Controller的ControllerDescriptor，还是用于描述Action方法的ActionDescriptor，都具有同步和异步两个版本，那么这些不同类型的ControllerDescriptor的ActionDescriptor是在什么情况下创建的呢？&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font size="4"&gt;&lt;font style="font-weight: bold"&gt;一、ControllerActionInvoker与AsyncControllerActionInvoker&lt;/font&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;ControllerDescriptor的创建设计到一个重要的名为ActionInvoker的组件，顾名思义，ActionInvoker专门用于Action方法的执行。我们会在本书第7章“Action方法的执行”中对ActionInvoker进行深入介绍，在这里我们只需要对其作一个简单的了解。&lt;/p&gt;  &lt;p&gt;ActionInvoker实现了具有如下定义的&lt;a title="IActionInvoker Interface" href="http://msdn2.microsoft.com/dd492736.aspx"&gt;IActionInvoker&lt;/a&gt;接口，唯一的方法实现了对指定Action方法的执行，而作为Controller的默认基类的&lt;a title="Controller Class" href="http://msdn2.microsoft.com/dd460481.aspx"&gt;Controller&lt;/a&gt;具有一个ActionInvoker属性，该属性表示的ActionInvoker被真正用于定义在该Controller类型中的所有Action方法的执行。&lt;/p&gt;  &lt;div id="codeSnippetWrapper"&gt;   &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;     &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;interface&lt;/span&gt; IActionInvoker&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;bool&lt;/span&gt; InvokeAction(ControllerContext controllerContext, &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; actionName);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;abstract&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; Controller&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt; {   &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt;     &lt;span style="color: #008000"&gt;//其它成员&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; IActionInvoker ActionInvoker { get; set; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum10"&gt;  10:&lt;/span&gt; }&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;而具有如下定义的System.Web.Mvc.Async.IAsyncActionInvoker接口是ActionInvoker的异步版本。IAsyncActionInvoker继承了IActionInvoker接口，并在此基础上定义了两个BeginInvokeAction/EndInvokeAction方法用于Action方法的异步执行。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;interface&lt;/span&gt; IAsyncActionInvoker : IActionInvoker&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     IAsyncResult BeginInvokeAction(ControllerContext controllerContext,  &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; actionName, AsyncCallback callback, &lt;span style="color: #0000ff"&gt;object&lt;/span&gt; state);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;bool&lt;/span&gt; EndInvokeAction(IAsyncResult asyncResult);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt; }&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;ASP.NET MVC真正用于Action方法同步和异步执行的ActionInvoker分别是&lt;a title="ControllerActionInvoker Class" href="http://msdn2.microsoft.com/dd460503.aspx"&gt;ControllerActionInvoker&lt;/a&gt;和&lt;a title="AsyncControllerActionInvoker Class" href="http://msdn2.microsoft.com/ee703547.aspx"&gt;AsyncControllerActionInvoker&lt;/a&gt;。如下面的代码片断所示，ControllerActionInvoker定义了一个受保护的方法GetControllerDescriptor用于根据指定的Controller上下文获取相应的ControllerDescriptor，它的子类AsyncControllerActionInvoker对这个方法进行了重写。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; ControllerActionInvoker : IActionInvoker&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color: #008000"&gt;//其它成员&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;protected&lt;/span&gt; &lt;span style="color: #0000ff"&gt;virtual&lt;/span&gt; ControllerDescriptor GetControllerDescriptor( ControllerContext controllerContext);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; AsyncControllerActionInvoker : ControllerActionInvoker,  IAsyncActionInvoker, IActionInvoker&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt; {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt;     &lt;span style="color: #008000"&gt;//其它成员&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum10"&gt;  10:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;protected&lt;/span&gt; &lt;span style="color: #0000ff"&gt;override&lt;/span&gt; ControllerDescriptor GetControllerDescriptor( ControllerContext controllerContext);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum11"&gt;  11:&lt;/span&gt; }&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;我们所有要了解的是在默认情况下（没有对Controller类型的ActionInvoker属性进行显式设置）采用的ActionInvoker类型是哪个。ASP.NET MVC对Conroller采用的ActionInvoker类型的选择机制是这样的：&lt;/p&gt;&lt;ul&gt;  &lt;li&gt;&lt;font color="#ff0000"&gt;通过当前的DependencyResolver以IAsyncActionInvoker接口去获取注册的ActionInvoker，如果返回对象不为Null，则将其作为默认的ActionInvoker&lt;/font&gt;。 &lt;/li&gt;  &lt;li&gt;&lt;font color="#ff0000"&gt;通过当前的DependencyResolver以IActionInvoker接口去获取注册的ActionInvoker，如果返回对象不为Null，则将其作为默认的ActionInvoker&lt;/font&gt;。 &lt;/li&gt;  &lt;li&gt;&lt;font color="#ff0000"&gt;创建AsyncControllerActionInvoker对象作为默认的ActionInvoker&lt;/font&gt;。 &lt;/li&gt;&lt;/ul&gt;&lt;p&gt;在默认的情况下，当前的DependencyResolver直接通过对指定的类型进行反射来提供对应的实例对象，所以对于前面两个步骤返回的对象均为Null，所以默认创建出来的ActionInvoker类型为AsyncControllerActionInvoker。我们可以通过如下一个简单的实例来验证这一点。在通过Visual Studio的ASP.NET MVC项目模板创建的空Web应用中，我们创建了如下一个默认的HomeController，在Action方法Index中直接通过ContentResult将ActionInvoker属性的类型名称呈现出来。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; HomeController : Controller&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {  &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; ActionResult Index()&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; Content(&lt;span style="color: #006080"&gt;&amp;quot;默认ActionInvoker类型:&amp;quot;&lt;/span&gt; + &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.ActionInvoker.GetType().FullName);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt; }   &lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;当运行该Web应用时，会在浏览器上产生如下的输出结果，我们可以清楚地看到默认采用的ActionInvoker类型正是AsyncControllerActionInvoker。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; 默认ActionInvoker类型:System.Web.Mvc.Async.AsyncControllerActionInvoker&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;为了进一步验证基于DependencyResolver对ActionInvoker的提供机制，我们将在《&lt;a href="http://www.cnblogs.com/artech/archive/2012/04/01/controller-activation-032.html"&gt;ASP.NET MVC Controller激活系统详解：IoC的应用[下篇]&lt;/a&gt;》创建的基于Ninject的自定义NinjectDependencyResolver应用在这里。如下面的代码片断所示，在初始化NinjectDependencyResolver的时候，我们将IActionInvoker和IAsyncActionInvoker影射到两个自定义ActionInvoker类型，即FooActionInvoker和FooAsyncActionInvoker，它们分别继承自ControllerActionInvoker和AsyncControllerActionInvoker。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; NinjectDependencyResolver : IDependencyResolver&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; IKernel Kernel { get; &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; set; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; NinjectDependencyResolver()&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.Kernel = &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; StandardKernel();&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt;         AddBindings();&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt;     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; AddBindings()&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum10"&gt;  10:&lt;/span&gt;     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum11"&gt;  11:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.Kernel.Bind&amp;lt;IActionInvoker&amp;gt;().To&amp;lt;FooActionInvoker&amp;gt;();&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum12"&gt;  12:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.Kernel.Bind&amp;lt;IAsyncActionInvoker&amp;gt;().To&amp;lt;FooAsyncActionInvoker&amp;gt;();&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum13"&gt;  13:&lt;/span&gt;     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum14"&gt;  14:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;object&lt;/span&gt; GetService(Type serviceType)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum15"&gt;  15:&lt;/span&gt;     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum16"&gt;  16:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.Kernel.TryGet(serviceType);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum17"&gt;  17:&lt;/span&gt;     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum18"&gt;  18:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; IEnumerable&amp;lt;&lt;span style="color: #0000ff"&gt;object&lt;/span&gt;&amp;gt; GetServices(Type serviceType)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum19"&gt;  19:&lt;/span&gt;     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum20"&gt;  20:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.Kernel.GetAll(serviceType);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum21"&gt;  21:&lt;/span&gt;     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum22"&gt;  22:&lt;/span&gt; }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum23"&gt;  23:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; FooActionInvoker : ControllerActionInvoker&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum24"&gt;  24:&lt;/span&gt; {}&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum25"&gt;  25:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; FooAsyncActionInvoker : AsyncControllerActionInvoker&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum26"&gt;  26:&lt;/span&gt; {}&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;在Global.asax中对NinjectDependencyResolver进行注册后运行我们的程序，会在浏览器中得到如下的输出结果。IAsyncActionInvoker和FooAsyncActionInvoker进行了影射，NinjectDependencyResolver可以通过IAsyncActionInvoker提供一个FooAsyncActionInvoker实例。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; 默认ActionInvoker类型:Artech.Mvc.FooAsyncActionInvoker&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;现在我们对NinjectDependencyResolver的定义稍加修改，将针对IAsyncActionInvoker接口的类型影射删除，只保留针对IActionInvoker的映射。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; NinjectDependencyResolver : IDependencyResolver&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color: #008000"&gt;//其它成员&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; AddBindings()&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.Kernel.Bind&amp;lt;IActionInvoker&amp;gt;().To&amp;lt;FooActionInvoker&amp;gt;();&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt;         &lt;span style="color: #008000"&gt;//this.Kernel.Bind&amp;lt;IAsyncActionInvoker&amp;gt;().To&amp;lt;FooAsyncActionInvoker&amp;gt;();&lt;/span&gt;&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt;     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt; }&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;再次运行我们的程序则会得到如下的输出结果。由于NinjectDependencyResolver只能通过IActionInvoker接口提供具体的ActionInvoker，所以最终被创建的是一个FooActionInvoker对象。这个实例演示告诉我们：当我们需要使用到自定义的ActionInvoker的时候，可以通过自定义DependencyResolver以IoC的方式提供具体的ActionInvoker实例。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; 默认ActionInvoker类型:Artech.Mvc.FooActionInvoker&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;&lt;strong&gt;&lt;font size="4"&gt;&lt;font style="font-weight: bold"&gt;二、ActionInvoker与ControllerDescriptor/ActionDescriptor&lt;/font&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;ControllerDescriptor和ActionDescriptor最终是为Model绑定服务的，而Model绑定是Action执行的一个环节，所以ControllerDescriptor最终是由相应的ActionInvoker创建的。总的来说，&lt;font color="#ff0000"&gt;用于同步Action执行的ControllerActionInvoker创建ReflectedControllerDescriptor，而用于异步Action执行的AsyncControllerActionInvoker则创建ReflectedAsyncControllerDescriptor&lt;/font&gt;。ActionInvoker和ControllerDescriptor之间的关系可以通过如下图所示的UML来表示。&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/artech/201205/201205110852178470.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/artech/201205/201205110852172025.png" width="463" height="264" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;对于ReflectedControllerDescriptor来说，包含其中的ActionDescriptor类型均为ReflectedActionDescriptor。而ReflectedAsyncControllerDescriptor描述的Controller可以同时包含同步和异步的Action方法，所以它可以包含任何类型的ActionDescriptor。&lt;/p&gt;&lt;p&gt;具体来说，&lt;font color="#ff0000"&gt;如果Action方法的返回类型为Task，对应的ActionDescriptor是一个TaskAsyncActionDescriptor对象&lt;/font&gt;。&lt;font color="#ff0000"&gt;如果Action方法名称包含“Async”后缀，并且存在一个对应的以“Completed”后缀的方法，则对应的ActionDescriptor是一个ReflectedAsyncActionDescriptor对象&lt;/font&gt;；如果对应Completed方法不存在，对应的FindAction方法会直接抛出一个InvalidOperationException异常。在其它情况下的Action方法均是同步的，所以对应的ActionDescriptor类型为ReflectedActionDescriptor。ControllerDescriptor与ActionDescriptor之间的关系如下图所示的UML来表示。&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/artech/201205/201205110852178404.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto; padding-top: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/artech/201205/201205110852174783.png" width="471" height="224" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;font size="4"&gt;&lt;font style="font-weight: bold"&gt;三、实例演示：AsyncActionInvoker对ControllerDescriptor的创建&lt;/font&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;为了让读者对ActionInvoker对ControllerDescriptor的解析机制具有一个深刻的理解，同时也作为对该机制的验证，我们做一个简单的实例演示。通过前面的介绍我们知道在默认的情况下Controller采用AsyncControllerActionInvoker进行Action方法的执行，这个例子就来演示一下它生成的ControllerDescriptor是个怎样的对象。我们通过Visual Studio的ASP.NET MVC项目模板创建一个空Web应用，并创建一个默认的HomeController，然后对其进行如下的修改。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;class&lt;/span&gt; HomeController : AsyncController&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; Index()&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt;     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum5"&gt;   5:&lt;/span&gt;         MethodInfo method = &lt;span style="color: #0000ff"&gt;typeof&lt;/span&gt;(AsyncControllerActionInvoker).GetMethod(&lt;span style="color: #006080"&gt;&amp;quot;GetControllerDescriptor&amp;quot;&lt;/span&gt;, BindingFlags.Instance | BindingFlags.NonPublic);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum6"&gt;   6:&lt;/span&gt;         ControllerDescriptor controllerDescriptor = (ControllerDescriptor)method.Invoke(&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.ActionInvoker, &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; &lt;span style="color: #0000ff"&gt;object&lt;/span&gt;[] { &lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.ControllerContext });&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum7"&gt;   7:&lt;/span&gt;         Response.Write(controllerDescriptor.GetType().FullName + &lt;span style="color: #006080"&gt;&amp;quot;&amp;lt;br/&amp;gt;&amp;quot;&lt;/span&gt;);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum8"&gt;   8:&lt;/span&gt;         CheckAction(controllerDescriptor, &lt;span style="color: #006080"&gt;&amp;quot;Foo&amp;quot;&lt;/span&gt;);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum9"&gt;   9:&lt;/span&gt;         CheckAction(controllerDescriptor, &lt;span style="color: #006080"&gt;&amp;quot;Bar&amp;quot;&lt;/span&gt;);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum10"&gt;  10:&lt;/span&gt;         CheckAction(controllerDescriptor, &lt;span style="color: #006080"&gt;&amp;quot;Baz&amp;quot;&lt;/span&gt;);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum11"&gt;  11:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum12"&gt;  12:&lt;/span&gt;     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum13"&gt;  13:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;private&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; CheckAction(ControllerDescriptor controllerDescriptor, &lt;span style="color: #0000ff"&gt;string&lt;/span&gt; actionName)&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum14"&gt;  14:&lt;/span&gt;     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum15"&gt;  15:&lt;/span&gt;         ActionDescriptor actionDescriptor = controllerDescriptor.FindAction(&lt;span style="color: #0000ff"&gt;this&lt;/span&gt;.ControllerContext, actionName);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum16"&gt;  16:&lt;/span&gt;         Response.Write(&lt;span style="color: #0000ff"&gt;string&lt;/span&gt;.Format(&lt;span style="color: #006080"&gt;&amp;quot;{0}:{1}&amp;lt;br/&amp;gt;&amp;quot;&lt;/span&gt;,actionName, actionDescriptor.GetType().FullName));&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum17"&gt;  17:&lt;/span&gt;     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum18"&gt;  18:&lt;/span&gt;&amp;#160; &lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum19"&gt;  19:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; Foo() { }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum20"&gt;  20:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; BarAsync() { }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum21"&gt;  21:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; BarCompleted() { }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum22"&gt;  22:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; Task Baz()&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum23"&gt;  23:&lt;/span&gt;     {&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum24"&gt;  24:&lt;/span&gt;         &lt;span style="color: #0000ff"&gt;return&lt;/span&gt; &lt;span style="color: #0000ff"&gt;new&lt;/span&gt; Task(DoNothing);&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum25"&gt;  25:&lt;/span&gt;     }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum26"&gt;  26:&lt;/span&gt;     &lt;span style="color: #0000ff"&gt;public&lt;/span&gt; &lt;span style="color: #0000ff"&gt;void&lt;/span&gt; DoNothing() { }&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum27"&gt;  27:&lt;/span&gt; }&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;我们首先将HomeController的基类从Controller改为AsyncController，并定义了Foo、BarAsync/BarCompleted和Baz四个方法，我们知道它们对应着Foo、Bar和Baz三个Action，其中Foo是同步Action，Bar和Baz分别是两种不同定义形式（XxxAsync/XxxCompleted和Task）的异步Action。&lt;/p&gt;&lt;p&gt;CheckAction用于根据指定的Action名称从ControllerDescriptor对象中获取用于表示对应Action的ActionDescriptor对象，最终将类型名称呈现出来。在Index方法中，我们通过反射的方式调用当前ActionInvoker（一个AsyncControllerActionInvoker对象）的受保护方法GetControllerDescriptor或者用于描述当前Controller（HomeController）的ControllerDescriptor的对象，并将类型名称呈现出来。最后通过调用CheckAction方法将包含在创建的ControllerDescriptor对象的三个ActionDescriptor类型呈现出来。&lt;/p&gt;&lt;p&gt;当我们运行该程序的时候，在浏览器中会产生如下的输出结果，从中可以看出ControllerDescriptor类型为ReflectedAsyncControllerDescriptor。同步方法Foo对象的ActionDescriptor是一个ReflectedActionDescriptor对象；以XxxAsync/XxxCompleted形式定义的异步方法Bar对应的ActionDescriptor是一个ReflectedAsyncActionDescriptor对象；而返回类型为Task的方法Baz对应的ActionDescriptor类型则是TaskAsyncActionDescriptor。&lt;/p&gt;&lt;div id="codeSnippetWrapper"&gt;  &lt;div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; background-color: #f4f4f4; border-left-style: none; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &amp;#39;Courier New&amp;#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; border-right-style: none; font-size: 8pt; overflow: visible; padding-top: 0px" id="codeSnippet"&gt;    &lt;span style="color: #606060" id="lnum1"&gt;   1:&lt;/span&gt; System.Web.Mvc.Async.ReflectedAsyncControllerDescriptor&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum2"&gt;   2:&lt;/span&gt; Foo:System.Web.Mvc.ReflectedActionDescriptor&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum3"&gt;   3:&lt;/span&gt; Bar:System.Web.Mvc.Async.ReflectedAsyncActionDescriptor&lt;!--CRLF--&gt;    &lt;span style="color: #606060" id="lnum4"&gt;   4:&lt;/span&gt; Baz:System.Web.Mvc.Async.TaskAsyncActionDescriptor&lt;!--CRLF--&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&amp;#160;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/artech/archive/2012/05/10/controller-descriptor.html"&gt;ASP.NET MVC三个重要的描述对象：ControllerDescriptor&lt;/a&gt;  &lt;br /&gt;&lt;a href="http://www.cnblogs.com/artech/archive/2012/05/10/action-descriptor.html"&gt;ASP.NET MVC三个重要的描述对象：ActionDescriptor&lt;/a&gt;  &lt;br /&gt;&lt;a href="http://www.cnblogs.com/artech/archive/2012/05/11/controller-descriptor-and-action-descriptor-creation.html"&gt;ASP.NET MVC三个重要的描述对象：ControllerDescriptor与ActionDescriptor的创建机制&lt;/a&gt;  &lt;br /&gt;&lt;a href="http://www.cnblogs.com/artech/archive/2012/05/13/parameter-descriptor.html"&gt;ASP.NET MVC三个重要的描述对象：ParameterDescriptor&lt;/a&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/artech/aggbug/2495366.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/artech/archive/2012/05/11/controller-descriptor-and-action-descriptor-creation.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry></feed>
