閱讀84 返回首頁    go 阿裏雲 go 技術社區[雲棲]


ASP.NET MVC以ValueProvider為核心的值提供係統: ValueProviderFactory

在ASP.NET Model綁定係統中,用於提供數據值的ValueProvider對象通過ValueProviderFactory來創建。在ASP.NET MVC應用編程接口中,ValueProviderFactory繼承自ValueProviderFactory類。本篇文章隻要介紹基於ValueProviderFactory的ValueProvider的提供機製,以及如何通過自定義ValueProviderFactory實現我們需要的數據值的綁定方式。[本文已經同步到《How ASP.NET MVC Works?》中]

目錄
一、ValueProviderFactory
二、ValueProviderFactory的注冊
三、實例演示:創建一個自定義ValueProviderFactory

如下麵的代碼片斷所示,ValueProviderFactory是一個抽象類,唯一的抽象方法GetValueProvider用於實現基於指定Controller上下文的ValueProvider創建。

   1: public abstract class ValueProviderFactory
   2: {
   3:     public abstract IValueProvider GetValueProvider(ControllerContext controllerContext);
   4: }

下麵的列表列出了定義在Model綁定係統中的6個原生的ValueProviderFactory:

  • ChildActionValueProviderFactory:根據給定的Controller上下文創建一個ChildActionValueProvider對象。
  • FormValueProviderFactory:根據給定的Controller上下文創建一個FormValueProvider對象。
  • JsonValueProviderFactory:將以JSON形式表示的請求數據轉換成一個Dictionary<string, object>對象,並最終創建一個DictionaryValueProvider<object>對象。
  • RouteDataValueProviderFactory:根據給定的Controller上下文創建一個RouteDataValueProvider對象。
  • QueryStringValueProviderFactory:根據給定的Controller上下文創建一個QueryStringValueProvider對象。
  • HttpFileCollectionValueProviderFactory:根據給定的Controller上下文創建一個HttpFileCollectionValueProvider對象。

ValueProviderFactory在ASP.NET MVC應用中的注冊通過靜態類型ValueProviderFactories實現。如下麵的代碼片斷所示,ValueProviderFactories具有一個靜態隻讀屬性Factories返回一個表示ValueProviderFactory集合的ValueProviderFactoryCollection類型。

   1: public static class ValueProviderFactories
   2: {
   3:     public static ValueProviderFactoryCollection Factories { get; }
   4: }
   5:  
   6: public class ValueProviderFactoryCollection : Collection<ValueProviderFactory>
   7: { 
   8:     public ValueProviderFactoryCollection();
   9:     public ValueProviderFactoryCollection(IList<ValueProviderFactory> list);    
  10:     public IValueProvider GetValueProvider(ControllerContext controllerContext);
  11: }

ValueProviderFactoryCollection的GetValueProvider方法返回的是一個ValueProviderCollection對象,集合中的每個ValueProvider通過對應的ValueProviderFactory來創建。。

在默認的情況下ValueProviderFactories的Factories屬性表示的ValueProviderFactoryCollection包含了上麵我們介紹的6種ValueProviderFactory,次序(優先級)為:ChildActionValueProviderFactory、FormValueProviderFactory、JsonValueProviderFactory、RouteDataValueProviderFactory、QueryStringValueProviderFactory和。。

以ValueProvider為核心的值提供係統中涉及到了三類組件/類型,即用於具體實現數據值提供的ValueProvider,ValueProvider通過ValueProviderFactotry,而ValueProviderFactotry通過ValueProviderFactotries進行注冊。圖5-4所示的UML體現了三者之間的關係。

image

ASP.NET MVC提供的6種ValueProviderFactory基本上已經可以滿足我們絕大部分Model綁定需求,不過對於一些比較極端的場景,我們有可能需要自定義ValueProviderFactory。作為演示,我們創建一個的自定義ValueProviderFactory。

我們將自定義的ValueProviderFactory命名為HttpHeaderValueProviderFactory。如下麵的代碼片斷所示,HttpHeaderValueProviderFactory的定義非常簡單,在重寫的GetValueProvider方法中,我們將針對指定的Controller上下文得到HTTP報頭集合,並借此創建NameValueCollection對象。由於作為報頭名稱具有“-”字符,為了與參數命名規則相匹配,我們將該字符剔除。最終創建的實際上是一個NameValueCollectionValueProvider對象。

   1: public class HttpHeaderValueProviderFactory : ValueProviderFactory
   2: {   
   3:     public override IValueProvider GetValueProvider(ControllerContext controllerContext)
   4:     {
   5:         NameValueCollection requestData = new NameValueCollection();
   6:         var headers = controllerContext.RequestContext.HttpContext.Request.Headers;
   7:         foreach (string key in headers.Keys)
   8:         { 
   9:             requestData.Add(key.Replace("-",""),headers[key]);
  10:         }
  11:         return new NameValueCollectionValueProvider(requestData, CultureInfo.InvariantCulture);
  12:     }
  13: }

我們通過Visual Studio的ASP.NET MVC項目模板創建一個空Web應用,並創建一個具有如下定義的HomeController。默認的Action方法Index具有一係列的參數,從參數名稱我們可以看出它們代表一些常用的HTTP報頭。我們最終將代表HTTP報頭的參數值呈現出來。

   1: public class HomeController : Controller
   2: {       
   3:     public void Index(string connection, string accept, string  acceptCharset, string acceptEncoding ,string acceptLanguage, 
   4:         string host, string userAgent)
   5:     {
   6:         Response.Write(string.Format("{0}: {1}<br/>", "Connection", accept));
   7:         Response.Write(string.Format("{0}: {1}<br/>", "Accept-Charset", acceptCharset));
   8:         Response.Write(string.Format("{0}: {1}<br/>", "Accept Encoding", acceptEncoding));
   9:         Response.Write(string.Format("{0}: {1}<br/>", "Accept-Language", acceptLanguage));
  10:         Response.Write(string.Format("{0}: {1}<br/>", "Host", "host"));
  11:         Response.Write(string.Format("{0}: {1}<br/>", "User-Agent", userAgent));
  12:     }
  13: }

然後利用Global.asax中按照如下的方式利用靜態類型對我們自定義的HttpHeaderValueProviderFactory進行注冊。

   1: public class MvcApplication : System.Web.HttpApplication
   2: {  
   3:     //其他成員
   4:     protected void Application_Start()
   5:     {
   6:         //其他操作
   7:         ValueProviderFactories.Factories.Add(new HttpHeaderValueProviderFactory());
   8:     }
   9: }

當我們運行該程序的時候,會在瀏覽器中呈現如下的輸出結果,而輸出的結果正是當前請求的HTTP報頭列表。

   1: Connection: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
   2: Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
   3: Accept Encoding: gzip,deflate,sdch
   4: Accept-Language: en-US,en;q=0.8
   5: Host: host
   6: User-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.162 Safari/535.19


ASP.NET MVC以ValueProvider為核心的值提供係統: NameValueCollectionValueProvider
ASP.NET MVC以ValueProvider為核心的值提供係統: DictionaryValueProvider
ASP.NET MVC以ValueProvider為核心的值提供係統: ValueProviderFactory


作者:蔣金楠
微信公眾賬號:大內老A
微博:www.weibo.com/artech
如果你想及時得到個人撰寫文章以及著作的消息推送,或者想看看個人推薦的技術資料,可以掃描左邊二維碼(或者長按識別二維碼)關注個人公眾號(原來公眾帳號蔣金楠的自媒體將會停用)。
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁麵明顯位置給出原文連接,否則保留追究法律責任的權利。
原文鏈接

最後更新:2017-10-26 11:34:15

  上一篇:go  ASP.NET MVC以ValueProvider為核心的值提供係統: DictionaryValueProvider
  下一篇:go  ModelBinder——ASP.NET MVC Model綁定的核心