NameValueCollectionValueProvider
在進行Model綁定過程中,需要根據基於Action方法參數的綁定上下文從請求數據中提取相應的數據以提供相應的數據。具體來說,Model綁定的數據具有多個來源,可能來源於Post的表單或者JSON字符串,或者來源於當前的路由數據,也可能來源於請求地址的插敘字符串。ASP.NET MVC將這種基於不同數據來源的數據獲取/提供機制實現在一個叫做ValueProvider的組件中。
一、IValueProvider與ValueProviderResult
一般來講,一個ValueProvider采用的數據源是一個字典類型的數據結構,我們通過它從這個字典中獲取一個Key與當前綁定上下文匹配的值。ValueProvider實現了具有如下定義的接口IValueProvider,GetValue方法根據指定的Key從數據源中獲取對應的值對象,這個Key是基於當前綁定上下文的。這個Key和存在於數據源中對應數據條目的Key可能並非完全一致,後者可能在前者基礎上添加相應的前綴,而ContainsPrefix方法用於判斷數據源字典的Key是否具有指定的前綴。
1: public interface IValueProvider
2: {
3: bool ContainsPrefix(string prefix);
4: ValueProviderResult GetValue(string key);
5: }
IValueProvider的GetValue返回的是一個ValueProviderResult對象,我們可以將ValueProviderResult看成是對ValueProvider提供對象的封裝。如下面的代碼片斷所示,ValueProviderResult具有三個只讀屬性,其中RawValue表示原始的值對象。而AttemptedValue表示以值對象的字符串表示,該屬性主要用於顯示。
1: [Serializable]
2: public class ValueProviderResult
3: {
4: public ValueProviderResult(object rawValue, string attemptedValue, CultureInfo culture);
5: public object ConvertTo(Type type);
6: public virtual object ConvertTo(Type type, CultureInfo culture);
7:
8: public string AttemptedValue { get; }
9: public CultureInfo Culture { get; }
10: public object RawValue { get; }
11: }
ValueProviderResult提供了兩個ConvertTo方法重載以實現向指定目標類型的轉換。某些類型的格式化行為依賴於相應的語言文化(比如時間、日期和貨幣等),而這個輔助格式湖的語言文化信息通過Culture屬性表示。其中第一個ValueProviderResult方法重載通過屬性Culture表示的語言文化進行類型轉化。
二、NameValueCollectionValueProvider
前面已經說過,Model數據源一般具有類似於字典的結構,而NameValueCollection可以表示為Key不具有唯一性的字典,將NameValueCollection對象作為數據源的ValueProvider通過具有如下定義的NameValueCollectionValueProvider類型表示。表示數據源的NameValueCollection對象在構造函數中指定,構造函數的另一個CultureInfo類型的參數表示服務於數據轉換的語言文化信息。
1: public class NameValueCollectionValueProvider : IUnvalidatedValueProvider, IEnumerableValueProvider, IValueProvider
2: {
3: //其他成員
4: public NameValueCollectionValueProvider(NameValueCollection collection, CultureInfo culture);
5:
6: public virtual bool ContainsPrefix(string prefix);
7: public virtual IDictionary<string, string> GetKeysFromPrefix(string prefix);
8: public virtual ValueProviderResult GetValue(string key);
9: public virtual ValueProviderResult GetValue(string key, bool skipValidation);
10: }
11:
12: public interface IEnumerableValueProvider : IValueProvider
13: {
14: IDictionary<string, string> GetKeysFromPrefix(string prefix);
15: }
16:
17: public interface IUnvalidatedValueProvider : IValueProvider
18: {
19: ValueProviderResult GetValue(string key, bool skipValidation);
20: }
從上面的代碼片斷我們可以看到,除了IValueProvider接口,NameValueCollectionValueProvider還實現了IEnumerableValueProvider和IUnvalidatedValueProvider兩個接口。顧名思義,IEnumerableValueProvider主要用於針對目標類型為集合的數據提供,方法GetKeysFromPrefix以一字典的形式返回具有指定前綴的Key。在默認的情況下,在進行數據提供的同時會對數據進行驗證,而IUnvalidatedValueProvider接口提供了一個額外的GetValue方法是我們可以忽略對數據的驗證。