最近園子里首頁有好幾篇文章都是講異步編程的,尤其是幾篇講博客園自身的異步化建設的文章,看了以后很有收獲。
閑暇之余再重新查查資料溫故知新學習一遍,重新認識了SynchronizationContext、aspNetSynchronizationContext和ConfigureAwait。
最大的心得是,web異步化處理后,容易引發問題的一個重要方面就是請求上下文,也就是本文標題里的HttpContext.Current。
園子里fish-li寫過一篇HttpContext.Current并不是無處不在,寫的比較詳細深入,看過這篇文章你就會非常明確用了HttpContext.Current容易引發哪些問題了。
記得很早以前開發某項目,引入了一個外部日志組件,反匯編之后竟然發現有直接通過HttpContext.Current獲取ip、UserAgent、請求參數等信息的,當時就對同事說千萬不要在異步邏輯里調用這個組件里的任何記錄日志的方法,防止觸雷。
我的觀點是,不要輕易在任何地方(類庫)使用HttpContext.Current,因為它并非無處不在,盡量把HttpContext的當前請求對象保留起來,可以傳參或者供外部類庫回調時重新獲取請求上下文使用。
但是,很多類庫(包括MS自己的)的現有內部實現中都離不開HttpContext.Current,我這里并不是說類庫中充斥著HttpContext.Current就是一種bad design。根據我個人的分析,至少目前已被廣泛使用的FormsAutentication內部實現,滿滿的都是HttpContext.Current充斥其中,而且最核心的讀寫cookie的方法都依賴HttpContext.Current。如果完全適應各種異步場景,說不定也會碰到HttpContext.Current不靈的情況,目測還有可優化的空間^_^。
我們所熟悉的aspx,ascx,ashx,masterpage,MvcHandler,MvcRouteHandler和MvcHttpHandler等等,每一個類實現的背后都有Httpcontext的存在,是否也有HttpContext.Current這種暴力寫法?據我所知,反正Page類是有的。好奇查看了一下MVC3的源碼,搜索關鍵字“HttpContext.Current”,整個MVC3源碼匹配的行數為12行,MvcHandler和MvcHttpHandler確實有HttpContext.Current的出現,它最終作為PRocessRequest或BeginProcessRequest方法的內部邏輯的一部分或者當中的參數,我們還是能夠理解的。
參考:
http://www.survivalescaperooms.com/cmt/p/configure_await_false.html
http://www.survivalescaperooms.com/jesse2013/p/Asynchronous-Programming-In-DotNet.html
http://www.survivalescaperooms.com/fish-li/archive/2013/04/06/3002940.html
http://msdn.microsoft.com/zh-cn/magazine/jj991977.aspx
http://msdn.microsoft.com/en-us/magazine/gg598924.aspx
先看SignOut方法的代碼:
SignOut /// <summary> /// Removes the forms-authentication ticket from the browser. /// </summary> public static void SignOut() { FormsAuthentication.Initialize(); HttpContext current = HttpContext.Current; bool flag = current.CookielessHelper.DoesCookieValueExistInOriginal('F'); // Always clear the uri-cookie current.CookielessHelper.SetCookieValue('F', null); if (!CookielessHelperClass.UseCookieless(current, false, FormsAuthentication.CookieMode) || current.Request.Browser.Cookies) { string value = string.Empty; if (current.Request.Browser["supportsEmptyStringInCookieValue"] == "false") { value = "NoCookie"; } HttpCookie httpCookie = new HttpCookie(FormsAuthentication.FormsCookieName, value); httpCookie.HttpOnly = true; httpCookie.Path = FormsAuthentication._FormsCookiePath; //What's the significance of Oct 12 1999 httpCookie.Expires = new DateTime(1999, 10, 12); httpCookie.Secure = FormsAuthentication._RequireSSL; if (FormsAuthentication._CookieDomain != null) { httpCookie.Domain = FormsAuthentication._CookieDomain; } current.Response.Cookies.RemoveCookie(FormsAuthentication.FormsCookieName); current.Response.Cookies.Add(httpCookie); } if (flag) { current.Response.Redirect(FormsAuthentication.GetLoginPage(null), false); } }注意設置過期時間httpCookie.Expires = new DateTime(1999, 10, 12);這一行,是不是很好奇想問為什么設置為1999年10月12號?設置過期時間的方式有多種,為什么寫死這個魔幻時間,這個魔幻時間從哪里來的?
其實早在數年前就有人在stackoverflow上問過這個問題,“What's the significance of Oct 12 1999?”。
只要拋出問題,世上熱心的好漢何其多哉,能準確回答的,不能確切回答的,還有小道消息道聽途說的……
目前該問題已經關閉,共有12個可選答案,其中不乏有大神Scott Hanselman的回答,但最被推崇的竟然是排在Scott Hanselman后的那個說法,講的煞有介事頭頭是道,就看你信哪個了。
我的另一最大收獲是,原來NBA傳奇球星張伯倫大帥卒于1999年10月12號。
參考:http://stackoverflow.com/questions/701030/whats-the-significance-of-oct-12-1999
新聞熱點
疑難解答