前面學習mvc管道處理模型的時候,我們曉的HttpContext是貫穿全文的一個對象,在HttpRuntime產生,現在我們所謂的Asp.Net六大內置對象,其實就是HttpContext的屬性。具體為:
一:Request即是Http請求提供的各種信息
A:Request的Heads里面的信息,通過代碼:
1 public ActionResult Request() 2 { 3 List<string> requestHeads = new List<string>(); 4 foreach (var item in base.Request.Headers.AllKeys) 5 { 6 requestHeads.Add($"{item}:{base.Request.Headers[item]}"); 7 } 8 ViewData["requestHead"] = requestHeads; 9 return View(); 10 }
views:
1 @{ 2 Layout = null; 3 } 4 <html> 5 <head> 6 <meta name="viewport" content="width=device-width" /> 7 <title>Request</title> 8 </head> 9 <body> 10 <div> 11 RequestHeads:<br /> 12 @{ 13 foreach (var item in (List<string>)ViewData["requestHead"]) 14 { 15 <label>@item</label><br /> 16 } 17 } 18 <div> 19 </div> 20 </div> 21 </body> 22 </html>
得到的頁面結果如下,即是RequestHeads里面的信息都可以完整的獲取到,后台代碼可以通過:context.Request.Headers["鍵名"],其中還可以包含自定義的key,如BasicAuth; 其實請求信息的解讀是asp.net_isapi按照http協議解析出來的。

B:除此之外,還可以獲取到URL,Form,Params等很多信息,只要是HTTP請求過來的基本都能拿到,具體可以參考HttpRequestBase類的屬性url參數 form參數 url地址 urlreferer content-encoding,就是http請求提供的各種信息,后台里面都是可以拿到的context.Request.Headers["User-Agent"];包括自定義的--BasicAuth; 請求信息的解讀是asp.net_isapi按照http協議解析出來的
二:Response即是響應
mvc呈現最終都是使用Response.Write方式的輸出,總結下來 各種result擴展就是序列化然后通過response輸出,給客戶端響應內容,響應的內容除了body(json/html/file),其實還有很多東西,各種header等,然后把這些東西響應出去交給瀏覽器去用。之前我們有做過的壓縮,緩存,cookie等都是在Response中寫入的。然后瀏覽器會根據這些設置去做相應的設置。具體怎么設置Response響應的東西,我們來拿壓縮跟緩存來舉一個例子。代碼如下:
壓縮:
1 /// <summary> 2 /// 瀏覽器請求時---聲明支持的格式---默認IIS是沒有壓縮 3 /// ---檢測了支持的格式---響應時將數據壓縮(IIS服務器)---響應頭里加上Content-Encoding 4 /// ---瀏覽器先查看數據格式---按照壓縮格式解壓--(無論你是什么東西,都可以壓縮解壓) 5 /// 6 /// 壓縮是IIS 解壓是瀏覽器 7 /// 就像lucene分詞,重復的單元可以節約空間 8 /// </summary> 9 public class CompressActionFilterAttribute : ActionFilterAttribute 10 { 11 public override void OnActionExecuting(ActionExecutingContext filterContext) 12 { 13 var request = filterContext.HttpContext.Request; 14 var respose = filterContext.HttpContext.Response; 15 string acceptEncoding = request.Headers["Accept-Encoding"];//檢測支持格式 16 if (!string.IsNullOrWhiteSpace(acceptEncoding) && acceptEncoding.ToUpper().Contains("GZIP")) 17 { 18 respose.AddHeader("Content-Encoding", "gzip");//響應頭指定類型 19 respose.Filter = new GZipStream(respose.Filter, CompressionMode.Compress);//壓縮類型指定 20 } 21 } 22 }
緩存:
1 public class CacheFilterAttribute : ActionFilterAttribute 2 { 3 /// <summary> 4 /// 緩存時長 單位s 5 /// </summary> 6 private int _MaxSecond = 0; 7 public CacheFilterAttribute(int duration) 8 { 9 this._MaxSecond = duration; 10 } 11 public CacheFilterAttribute() 12 { 13 this._MaxSecond = 60; 14 } 15 /// <summary> 16 /// action執行后 17 /// </summary> 18 /// <param name="filterContext"></param> 19 public override void OnActionExecuted(ActionExecutedContext filterContext) 20 { 21 if (this._MaxSecond <= 0) return; 22 23 HttpCachePolicyBase cache = filterContext.HttpContext.Response.Cache; 24 TimeSpan cacheDuration = TimeSpan.FromSeconds(this._MaxSecond); 25 26 cache.SetCacheability(HttpCacheability.Public); 27 //cache.SetLastModified(DateTime.Now.AddHours(8).Add(cacheDuration)); 28 //cache.SetExpires(DateTime.Now.AddHours(8).Add(cacheDuration));//GMT時間 格林威治時間 29 cache.SetExpires(DateTime.Now.Add(cacheDuration)); 30 cache.SetMaxAge(cacheDuration); 31 cache.AppendCacheExtension("must-revalidate, proxy-revalidate"); 32 } 33 }
即是瀏覽器Response中得到的都可以進行設置操作:

三:Application即是全局的東西,多個用戶共享
我們曉得部署到IIS上面的項目是多並發的,即每個用戶訪問都有各自域,這些都是不共享的,各自在各自的域中運行解析,但是Application是提供了一個全局變量,即不會分域,每個訪問者都是使用的同一個Application。因為牽涉到是全局的,所以這個變量很少被使用到。但是可以通過這個變量來統計一下訪問量。但是每次使用時需要加鎖解鎖,不然高並發會有所影響。下面也介紹一下介個變量的一些使用方法:
1 #region Application 2 context.Application.Lock();//ASP.NET 應用程序內的多個會話和請求之間共享信息 3 context.Application.Lock(); 4 context.Application.Add("try", "die"); 5 context.Application.UnLock(); 6 object aValue = context.Application.Get("try"); 7 aValue = context.Application["try"]; 8 context.Application.Remove("命名對象"); 9 context.Application.RemoveAt(0); 10 context.Application.RemoveAll(); 11 context.Application.Clear(); 12 13 context.Items["123"] = "123";//單一會話,不同環境都可以用,比如在httpmodule獲取到的信息,想傳遞給action;隨着context釋放 14 #endregion
四:Server也就是個幫助類庫,具體詳情參考HttpServerUtilityBase,下面僅僅列取一些常用的方法:
1 #region Server 2 //輔助類 Server 3 string encode = context.Server.HtmlEncode("<我愛我家>"); //HtmlEnode編碼 4 string decode = context.Server.HtmlDecode(encode);//HtmlEnode解碼 5 6 string physicalPath = context.Server.MapPath("/Home/Index");//只能做物理文件的映射 7 string encodeUrl = context.Server.UrlEncode("<我愛我家>"); //URLencode編碼 8 string decodeUrl = context.Server.UrlDecode(encodeUrl); //URLencode解碼 9 #endregion
五: Session即是用戶第一次產生,一個用戶一個Session;是字典式存儲的;session保存的是sessionid和value,value是個集合,集合有個currentUser的key,即是一次SessionId可以對應多個key,一個key對應一個Value的值。
1:Session的一般用法:A:用戶登錄驗證,登錄時寫入,驗證時獲取; B:驗證碼;C:跳轉當前頁;
2:Session的代碼操作如下:
1 #region Session 的存儲,可以存儲各種各樣的值,然后以鍵值對的形式存儲 2 var currentUser = new CurrentUser() 3 { 4 Id = 1, 5 Name = "wss", 6 Remark = "test by wss " 7 }; 8 var context = base.HttpContext; 9 var sessionUser = context.Session["CurrentUser"]; 10 context.Session["CurrentUser"] = currentUser; 11 context.Session["CurrentUser1"] = "wss"; 12 context.Session["CurrentUser2"] = 111; 13 context.Session["CurrentUser3"] = DateTime.Now; 14 context.Session.Timeout = 3;//minute session過期等於Abandon,過期日期是滑動時間,即是每次訪問都會在當前訪問的時間上面增加3分鍾 15 #endregion 16 17 #region Session的取值,直接使用鍵即可,取出來的是object類型 18 var CurrentUser = context.Session["CurrentUser"]; 19 var CurrentUser1 = context.Session["CurrentUser1"]; 20 var CurrentUser2 = context.Session["CurrentUser2"]; 21 var CurrentUser3 = context.Session["CurrentUser3"]; 22 #endregion 23 24 #region Session的清除方式 25 context.Session["CurrentUser"] = null;//表示將指定的鍵的值清空,並釋放掉,但是session的key還是存在的 26 context.Session.Remove("CurrentUser"); //將session中的key跟value移除掉 27 context.Session.Clear();//表示將會話中所有的session的鍵值都清空,但是session還是依然存在, 28 context.Session.RemoveAll();//表示將會話中所有的session的鍵值都清空 29 context.Session.Abandon();//就是把當前Session對象刪除了,下一次就是新的Session了 ,介個使用同一個瀏覽器測試沒有出現想要的效果 30 #endregion:
3:Session的特點:
A:是服務器內存(sessionstateserver/SQLServer),所以體積不要太大,可以存敏感信息,但是重啟丟失。
B:因為一個用戶針對於一條session,而且session是存儲在內存中,那如果負載均衡下面的session如果共享呢,可以通過會話粘滯/session存儲在固定的服務中來解決介個問題
C:mvc中的Tempdate是使用Session來傳值的。
六:Cookie是存儲在客戶端(瀏覽器)上面的一連串字符串,一個用戶一個Cookie,字典式存儲;
1:Cookie的使用方向:A:用戶登錄驗證,登錄時寫入,驗證時獲取;B: ValidateAntiForgeryToken;C:保存用戶數據(記住賬號;購物車;訪問過那幾個頁面;);
2:cookie的代碼使用:
1 var context = base.HttpContext; 2 var currentUser = new CurrentUser() 3 { 4 Id = 1, 5 Name = "wss", 6 Remark = "test by wss Cookie" 7 }; 8 #region cookie的存儲 9 10 HttpCookie myCookie = new HttpCookie("CurrentUser"); 11 myCookie.Value = JsonHelper.ObjectToString<CurrentUser>(currentUser); //只能是字符串 12 myCookie.Expires = DateTime.Now.AddMinutes(5);//如果設置Expires,則會保存到硬盤,不設置就是內存cookie--關閉瀏覽器就丟失 13 context.Response.Cookies.Add(myCookie);//一定要輸出 14 15 #endregion 16 17 #region cookie的取值 18 HttpCookie myCookie1 = context.Request.Cookies["CurrentUser"]; 19 #endregion 20 21 #region cookie的清除,注意cookie沒有移除等方法,只能設置過期時間 22 if (myCookie1 != null) 23 { 24 myCookie1.Expires = DateTime.Now.AddMinutes(-1);//設置過過期 25 context.Response.Cookies.Add(myCookie1); 26 } 27 #endregion
3:cookie的特點:
- A:因為cookie是存在客戶端,所以不能有敏感信息,而且cookie推薦加密
- B:因為每次請求都提交,這個是瀏覽器的特性,所以cookie不能太大,否則會影響性能
- C:可以不指定expiretime,這樣就可以存瀏覽器內存,然后關閉瀏覽器就cookie就丟失了
- E:如果想存在硬盤就指定expiretime,如存在硬盤,以后想清空就修改有效期,否則不會丟失
- F:cookie是跟瀏覽器有關系的,同一個瀏覽器登陸能覆蓋,因為一個瀏覽器cookie只有一個地方存儲,不同的瀏覽器登陸就不會覆蓋,另外無痕模式是不會覆蓋的
- G:cookie是不跨域的
七:http協議:超文本傳輸協議,也就是個文本傳輸的規范;瀏覽器/客戶端遵循;服務端也遵循,那么就可以發起交互了,具體就是靠文本來傳輸的,其實文本就是按照規范來拼接好的一連串字符串。具體請求如下圖

跨域:瀏覽器A域名去訪問B域名的東西,但是瀏覽器限制了跨域的請求,如果想要解決,就是服務響應的時候,增加響應頭original-
八:Cookie跟Session的關系
是因為Http協議是無狀態的,因此但是后面又想客戶端跟服務器端進行交互,所以就產生的cookie跟session,具體他們之間交互的過程請看下圖:

所以第一次客戶訪問會產生一個sessionid,然后寫在cookie中,等下次客戶再訪問時,會把cookie中的sessionid帶上,這樣就曉得該客戶的一些行為。
注意:sessionid會存在cookie中,那如果客戶端把cookie禁用掉,那session還生效嗎?答案是否定的,如果想要生效,必須通過URL或者隱藏文本框等其它渠道來解決。
