前言
在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模式下進行,不太肯定這樣的測試是否嚴謹和正確,歡迎大家批評)。