前言
在WebAPi中我們通常需要得到請求資訊中的查詢字元串或者請求頭中資料再或者是Cookie中的資料,如果需要大量擷取,此時我們應該想到封裝一個擴充類來添加擴充方法,進而實作簡便快捷的擷取。
WebAPi常用擴充方法
(1)擷取所有鍵值對
/// <summary> /// 擷取所有鍵值 /// </summary> /// <param name="request"></param> /// <returns></returns> public static Dictionary<string, string> GetQueryStrings(this HttpRequestMessage request) { return request.GetQueryNameValuePairs().ToDictionary(k => k.Key, v => v.Value, StringComparer.OrdinalIgnoreCase); }
(2)擷取單個key對應value
/// <summary> /// 擷取單個鍵值 /// </summary> /// <param name="request"></param> /// <param name="key"></param> /// <returns></returns> public static string GetQueryString(this HttpRequestMessage request, string key) { var queryStrings = request.GetQueryNameValuePairs(); if (queryStrings == null) return null; var match = queryStrings.FirstOrDefault(kv => string.Compare(kv.Key, key, true) == 0); if (string.IsNullOrEmpty(match.Value)) return null; return match.Value; }
注意:請不要告訴我用HttpContext.Current.Request.QueryString["key"]去擷取鍵值,在WebHost模式下是可以的,但是在SelfHost模式下該對象是為空的。
(3)擷取請求頭中對應鍵值
/// <summary> /// 依據鍵擷取請求頭中值資料 /// </summary> /// <param name="request"></param> /// <param name="key"></param> /// <returns></returns> public static string GetHeader(this HttpRequestMessage request, string key) { IEnumerable<string> keys = null; if (!request.Headers.TryGetValues(key, out keys)) return null; return keys.First(); }
(4)擷取Cookie中鍵值
/// <summary> /// 擷取Cookie /// </summary> /// <param name="request"></param> /// <param name="cookieName"></param> /// <returns></returns> public static string GetCookie(this HttpRequestMessage request, string cookieName) { CookieHeaderValue cookie = request.Headers.GetCookies(cookieName).FirstOrDefault(); if (cookie != null) return cookie[cookieName].Value; return null; }
思維發散
我們知道在ASP.NET中擷取請求參數值時用QueryString、在擷取擷取Web.config配置中值時、以及請求頭中有時候會用到NameValueCollection,在上述中我們傳回的是Dictionary<string,string>,那Dictionary和NameValueCollection在擷取參數時有什麼差別呢?
NameValueCollection
我們來看看其具體用法,在此類中添加對應資料并擷取:
static NameValueCollection GetCollection() { var collection = new NameValueCollection(); collection.Add("張三", "部落格園"); collection.Add("李四", "csdn"); collection.Add("李四", "51cto"); collection.Add("張三", "IBM"); return collection; }
進行列印:
var collection = GetCollection(); foreach (string key in collection.AllKeys) { Console.WriteLine(key); Console.WriteLine(collection[key]); }

從上可以看出,此時的鍵沒有重複傳回,但是此時每一個鍵會映射到一個字元串數組即裡面存的是相同的鍵所對應的值。是以我們可以得出結論通過AllKeys屬性來進行周遊NameValueCollection集合時此時傳回的鍵是所有未重複的鍵。
此時我們若取某個不存在的鍵結果會是怎樣呢?
Console.WriteLine(collection["xpy0928"] == null);
此時會列印出True。
基于此我們可以得出結論:
當在NameValueCollection集合中依據鍵去取值時,若有多個值被找到,此時則會傳回以逗号隔開的字元串數組,若未找到則傳回空。
接下來我們看看該集合的其他方法:
Console.WriteLine(collection.HasKeys()); Console.WriteLine(collection.GetKey(0)); string value = collection.Get(0); Console.WriteLine(value);
(1)第一個顯示該集合中是否存在鍵值(傳回True)。
(2)擷取該集合的第一個鍵(傳回張三)。
(3)擷取第一鍵對應的值(傳回部落格園,IBM)。
上述都是關于判斷鍵以及取鍵值的情況,當然裡面還有添加和移除的方法,添加我們不必多說,我們來看看移除的方法。
collection.Remove("張三"); collection.Remove("xpy0928"); foreach (var key in collection.AllKeys) { Console.WriteLine(key); Console.WriteLine(collection[key]); }
當移除已存在的鍵時,此時則會删除該鍵對應的所有值,但是很有意思的是移除一個不存在的鍵時根本不會抛出異常。
Dictionary
接下來我們看看Dictionary。
static Dictionary<string, string> GetDict() { var dictionary = new Dictionary<string, string>(); dictionary.Add("張三", "部落格園"); dictionary.Add("李四", "csdn"); dictionary.Add("王五", "51cto"); dictionary.Add("趙六", "IBM"); return dictionary; }
我們添加一項看看
var dict = GetDict(); dict.Add("張三", "部落格園");
在字典中不能添加重複項。
至此,我們可以得出結論:在NameValueCollection與Dictionary上最主要的差別在于NameValueCollection可以添加重複項,而Dictionary不行。
當然在字典中去移除不存在的鍵也不會抛出異常,如下:
dict.Remove("xpy928");
接下來我們來看看二者在查找資料時是否有性能上的差異,我們在Release模式來進行操作。
var collection = GetCollection(); var dict = GetDict(); var stopWatch = new Stopwatch(); stopWatch.Start(); for (int i = 0; i < 100000000; i++) { string value = collection["張三"]; } var time = stopWatch.ElapsedMilliseconds; Console.WriteLine(time); stopWatch.Stop(); var stopWatchDict = new Stopwatch(); stopWatchDict.Start(); for (int i = 0; i < 100000000; i++) { string value = dict["張三"]; } var time1 = stopWatchDict.ElapsedMilliseconds; Console.WriteLine(time1); stopWatchDict.Stop();
如上我們疊代10億次來看看二者在查找資料上有沒有性能差異:
這裡我們可以看到用NameValueCollection去擷取資料時耗時48秒,而用Dictionary則耗時4秒,從此可以看出二者除了在添加資料上的差異還有在疊代查詢資料時也有很大的性能差異。
總結
上述我們主要講述WebAPi中添加常用可能會用到擷取參數的擴充方法,同時也比較了NameValueCollection和Dictionary除了在添加資料上是否可以允許有重複項外而且在疊代資料上也有很大的性能差異(上述疊代在Release模式下進行,不太肯定這樣的測試是否嚴謹和正确,歡迎大家批評)。
所有的選擇不過是為了下一次選擇做準備