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體現了三者之間的關係。
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