摘要
其實你一看到,就應該會想到,這個不簡單嗎,不就是服務端接收參數的兩種方式嗎?是的。在asp.net編程中,QueryString、Form、Cookie是三種比較常見的接收客戶端參數的方式。QueryString:接收包含在url中的參數。Form:接收表單數據。Cookie可以獲取會話狀態中保存的信息(大部分情況下用來存儲用戶信息)。除了這些外,HttpRequest還提供了ServerVariables來讓我們獲取一些來自web服務器變量。
問題來了?
其實通常情況下,我們知道傳遞的參數來自哪,可以使用QueryString,Form明確的來接收url或者表單中的數據。但服務端接口為了既可以通過url獲取參數,又可以通過Form獲取參數,該如何呢?(當然,規定調用方必須通過url或者Form某一種方式除外)。那么就要用到Request[]或者Request.Params[]這兩種方式獲取來自客戶端提交的數據了。但,到底用哪個?
下面先看一個例子:
public ActionResult Index() { ViewBag.requestParams = Request.Params["name"]; ; ViewBag.request = Request["name"]; return View(); }
有這樣一個action,我們用來獲取url中傳遞的參數name。這兩種方式有什么區別呢?你猜....
到這里,你會發現,這兩種方式,不一樣嗎?都可以接收正確的參數。但還是有特殊情況。
我們添加一個cookie的action,向客戶端添加一個以name為鍵的值,代碼如下:
public string Cookie() { Response.Cookies.Add(new HttpCookie("name", "wolfy") { Expires = DateTime.Now.AddDays(1) }); return "cookie writes successfully!"; }
然后我們再訪問一下,Index頁面。
發現了不同了吧。你可以說,你這種方式太奇葩了,哪有那么巧參數名稱一樣,但一個項目多個人來合作完成,參數名稱名稱相同還是很有可能的。所以不小心就會出現這種問題,不小心就會中招,掉坑里的。
到底為什么?
源碼:https://github.com/Microsoft/referencesource
我們先看一下Params的實現。
// Params collection - combination of query string, form, server vars // Gets a combined collection of QueryString+Form+ ServerVariable+Cookies. public NameValueCollection Params { get { if (HttpRuntime.HasAspNetHostingPermission(AspNetHostingPermissionLevel.Low)) return GetParams(); else return GetParamsWithDemand(); } }
private NameValueCollection GetParams() { if (_params == null) { _params = new HttpValueCollection(64); FillInParamsCollection(); _params.MakeReadOnly(); } return _params; } [AspNetHostingPermission(SecurityAction.Demand, Level=AspNetHostingPermissionLevel.Low)] private NameValueCollection GetParamsWithDemand() { return GetParams(); }
// Params collection support private void FillInParamsCollection() { _params.Add(this.QueryString); _params.Add(this.Form); _params.Add(this.Cookies); _params.Add(this.ServerVariables); }
通過上面的代碼可以看到Params是NameValueCollection鍵值對類型的只讀屬性,在FillInParamsCollection方法中,將QueryString,Form,Cookies,ServerVariables加入到了字段中。這就說明了上面的例子中,為什么Params[key]會取到QueryString和cookie里面的值了。
我們在看一下Request[key]的實現。
// Default property that goes through the collections // QueryString, Form, Cookies, ClientCertificate and ServerVariables public String this[String key] { get { String s; s = QueryString[key]; if (s != null) return s; s = Form[key]; if (s != null) return s; HttpCookie c = Cookies[key]; if (c != null) return c.Value; s = ServerVariables[key]; if (s != null) return s; return null; } }
可以看到Request[key]的實現方式,查找順序是QueryString,Form,Cookies,ServerVariables,直到找到然后直接返回。
總結
一直對Request.Params[key]和Request[key]比較困惑,在這里也掉過坑,最近在項目中,又看到了,所以,就趁着扒了一下源碼。
感興趣的可以或者對以前用法不太理解的可以扒一扒源碼,或許可以可以解惑。
資料