上一個隨筆主要針對HttpModeul[ASP.NET基礎之HttpModule學習]內容進行一個簡單的學習;本章內容我將對ASP.NET另一個主要的知識點HttpContext進行學習;首先我們簡單了解一些理論的知識,然后結合一些實例演示我們開發時經常要用到的一些功能,其中有些部分是從網上整理所得,希望對您的閱讀有所幫助;
一:HttpContext理論知識:
1:HttpContext類它對Request、Respose、Server等等都進行了封裝,並保證在整個請求周期內都可以隨時隨地的調用;為繼承 IHttpModule 和 IHttpHandler 接口的類提供了對當前 HTTP 請求的 HttpContext 對象的引用。該對象提供對請求的內部Request、Response 和 Server 屬性的訪問。HttpContext的命名空間:System.Web(在 system.web.dll 中);除了對幾個對象進行封裝外它還有個HttpContext.Item,通過它你可以在HttpContext的生存周期內提前存儲一些臨時的數據,方便隨時使用。
2:生存周期:從客戶端用戶點擊並產生了一個向服務器發送請求開始---服務器處理完請求並生成返回到客戶端為止。針對每個不同用戶的請求,服務器都會創建一個新的HttpContext實例直到請求結束,服務器銷毀這個實例。
3:當我們創建一個一般處理程序Handler.ashx時,我們可以在文件中看到這一句 public void ProcessRequest (HttpContext context);
4:可以通過HttpContext.Current獲得當前的上下文httpContext的內容;這樣可以在多處方便獲取我們想要的數據;
二:HttpContext.Item的運用
在文中第一點我們有提到HttpContext.Item可以通過它來存儲一些臨時的數據;我們將通過一個實例來演示它的實現,以及在此過程中應該注意什么;還針對ASP.NET常見的兩種跳轉進行比較(分別為:Server.Transfer和Response.Redirect);
1:首先我們新建一個頁面對HttpContext.Item它進行寫入數據(此處不一樣的是當寫完值后不同的頁面跳轉方式):
protected void Btn_Transfer_Click(object sender, EventArgs e) { List<String> list = new List<string>(); list.Add("踏浪帥"); list.Add("www.cnblogs.com/wujy"); HttpContext.Current.Items["TransferName"] = list; Server.Transfer("Index.aspx"); } protected void Btn_Redirect_Click(object sender, EventArgs e) { List<String> list = new List<string>(); list.Add("踏浪帥"); list.Add("www.cnblogs.com/wujy"); HttpContext.Current.Items["RedirectName"] = list; Response.Redirect("Index.aspx"); }
接着我們再新建一個Index.aspx頁面接收此頁面的值:
public partial class Index : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { if(!IsPostBack) { List<string> list = HttpContext.Current.Items["TransferName"] as List<string>; if (list != null) { foreach (string item in list) { Response.Write(string.Format("Transfer輸出的值為:{0} <br/>", item)); } } List<string> ResList = HttpContext.Current.Items["RedirectName"] as List<string>; if (ResList != null) { foreach (string item in ResList) { Response.Write(string.Format("Redirect輸出的值為:{0}", item)); } } else { Response.Write("Response.Redirect傳過來為空!"); } } } }
現在我們看一下運行的效果:
Server.Transfer方式 | Response.Redirect方式 |
![]() |
![]() |
從上面運行的結果我們不然發現使用Server.Transfer方式我們在接收頁面成功獲得我們寫入的數據;而Response.Redirect方式卻導致數據的丟失;出現這個問題的原因是Server.Transfer是在服務器直接操作的的和調用的地方屬於同一次http請求,此處如果使用Response.Redirect是從客戶端重新發起了一次Http請求;而正如我們前面所說的HttpContext的生存周期只能在一個http請求才不會被服務器銷毀這個實例;
針對上面Server.Transfer是在服務器直接操作和調用的我們其實可以看一下我們跳轉時URL地址的變化就知道了,URL它是沒有變化的;
Server.Transfer | |
![]() |
![]() |
而Response.Redirect跳轉后的URL地址是發生變化(它是從客戶端再去做起一次請求訪問到index.aspx頁面):
注意:一般的情況下盡可能用Server.Transfer方法(前提是服務器是IIS),Server.Transfer方法更快速,而且因為只在服務器上執行,所以可以和任何瀏覽器兼容。
Response.Redirect其實上是當服務器碰到這條語句時發送一條指令(包含新的地址)給瀏覽器,然后讓瀏覽器去發送http請求,請求Response.Redirect后面的那個新的http地址,流程如下:瀏覽器文件請求->服務器執行->遇到response.redirect語句->服務器發送Server.Transfer后面的地址給客戶機端的瀏覽器->瀏覽器請求執行新的地址(服務器返回的Response.Redirect后面的地址)這就是一個小小的Response.Redirect的全部過程,
Server.Transfer語句當接受地址后是直接轉向后面的地址,流程如下:瀏覽器文件請求->服務器執行->遇到Server.Transfer語句->服務器轉向新的文件。
2:截獲Http請求並作特殊處理
主要是用在Application_BeginRequest方法里。Application_BeginRequest方法在global.asax.cs里定義。你可以在Http請求剛剛開始的時候,截獲他,做一些特殊的處理。這里你不能用Session來做,因為此時Session對象還沒有被建立。 利用Context.Item集合,你可以在Http請求的整個生命期,通過HttpModules, HttpHandlers, Webforms, and Application 事件。
三:HttpContet對象之Request
1:Request理論知識:
ASP.NET Request 封裝了客戶端請求信息,是從客戶端得到數據(從瀏覽器獲取數據);常用的三種取得數據的方法是:Request.Form、Request.QueryString、Request其第三種是前兩種的一個縮寫,可以取代前兩種情況。而前兩種主要對應的Form提交時的兩種不同的提交方法:分別是Post方法和Get方法。
2:新建一個頁面用來顯示Requesst一些常見屬性信息的內容;
public partial class RequestPage : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { StringBuilder strBuider = new StringBuilder(); strBuider.Append("客戶端主機的IP地址:" + HttpContext.Current.Request.UserHostAddress + "</br>"); strBuider.Append("客戶端瀏覽器版本:" + Request.UserAgent + "</br>"); strBuider.Append("當前由哪個頁面URL跳轉過來:" + Request.UrlReferrer+ "</br>"); strBuider.Append("當前要求的URL:" + Request.Url + "</br>"); strBuider.Append("當前要求的URL絕對地址:" + Request.Url.AbsolutePath + "</br>"); strBuider.Append("當前要求的URL絕對URI:" + Request.Url.AbsoluteUri + "</br>"); strBuider.Append("當前要求的URL主機名跟端口:" + Request.Url.Authority + "</br>"); strBuider.Append("當前要求的URL實例主機的一部分:" + Request.Url.Host + "</br>"); strBuider.Append("當前要求的URL端口:" + Request.Url.Port + "</br>"); strBuider.Append("當前要求的URL的內容第一個段:" + Request.Url.Segments[0] + "</br>"); strBuider.Append("當前要求的URL的內容第二個段:" + Request.Url.Segments[1] + "</br>"); strBuider.Append("當前要求的URL的內容第三個段:" + Request.Url.Segments[2] + "</br>"); strBuider.Append("瀏覽器地址欄后的參數"+Request.QueryString + "</br>"); strBuider.Append("當前網頁在服務器端的實際路徑:" + Request.PhysicalPath + "</br>"); strBuider.Append("當前文件的物理地址:" + Request.PhysicalApplicationPath + "</br>"); strBuider.Append("當前網頁的相對地址:" + Request.Path + "<br/>"); strBuider.Append("當前頁面的URL:" + Request.RawUrl + "<br/>"); strBuider.Append("客戶端上傳的文件(個數):" + Request.Files.Count + "<br/>"); strBuider.Append("當前執行網頁的相對地址:" + Request.FilePath + "<br/>"); strBuider.Append("客戶端瀏覽器的信息:" + Request.Browser + "<br/>"); strBuider.Append("當前運行程序的服務器端虛擬目錄:" + Request.ApplicationPath + "<br/>"); strBuider.Append("客戶端瀏覽器的字符設置:" + Request.ContentEncoding + "<br/>"); Response.Write(strBuider.ToString()); } } }
運行結果顯示(獲得客戶端瀏覽器以及一些相關的信息):
3:針對表單的提交方式如上面所說的有兩種方式(POST以及GET);接下來我們則通過幾段代碼來演示有關表單提交的兩種方式以及一些應該注意的事項;
(1)表單Get方式提交:
相信在我們平常的開發過程中使用Get方式進行提交的表單是最經常碰到的,它也是最簡單的一種方式,主要注意在使用Get提交時URL對數據的大小是有限止;還經常碰到的情況是對URL傳參時一些特殊符號的處理問題;接下來我們將通過小實例來演示兩種對URL傳參處理特殊符號方式;
首先是使用ASP.NET代碼的Server對象對要傳參進行一個編碼的處理(Server.UrlEncode(string s));
string UserName = "踏浪帥¥%—*@"; Server.Transfer("GetPageResult.aspx?UserName="+Server.UrlEncode(UserName)+"&UserID=001");
接上時再對收到的參數進行一個解碼(Get方式使用Request.QueryString[Name]和Request[Name]進行接收參數;解碼Server.UrlDecode(string s)):
string UserName = Request.QueryString["UserName"]; Response.Write("第一個傳參值:" + Server.UrlDecode(UserName) + "</br>"); string UserID = Request["UserID"]; Response.Write("第二個傳參值:" + UserID + "</br>");
查后運行結果:
另外一種方式是使用JS進行傳參,此得使用到的JS中的escape();而它接收解碼跟上面使用ASP.NET代碼是一樣;
<head runat="server"> <title></title> <script type="text/javascript" src="jquery-1.4.2.min.js"></script> <script language="javascript" type="text/javascript"> $(function () { $("#Btn_Get").bind('click',GetResult); }) function GetResult() { var UserName = "踏浪帥¥%—*@"; location.href = "GetPageResult.aspx?UserID=002&UserName="+escape(UserName); } </script> </head> <body> <form id="form1" runat="server"> <input id="Btn_Get" type="button" value="HTML中的JS傳值" /> </form> </body> </html>
運行結果:
(2)Post方式提交:
Post方式的表單提交比Get方式更加安全,它不會把我們要傳遞的參數顯示在URL里,還有它可以針對一些要傳遞內容比較大(比如文件上傳等);先通過一段代碼來演示此方式的提交;后面我們再順便介紹Post方式提交時常遇到的一個錯誤;
首先同樣新建一個頁面(我們把表單通過Post提交到PostPageResult.aspx頁面,method就是用來設置我們使用Post方式):
<head runat="server"> <title></title> </head> <body> <form id="form1" action="PostPageResult.aspx" method="post"> <div> Cnblogs賬號:<input type="text" size="20" name="Name" value="踏浪帥"/> <br /> <input type="submit" value="提交" /> </div> </form> </body> </html>
接收頁在的代碼(Post可以采用Request.Form[Name]和Request[Name]進行接收參數,若是提交過來有上傳文件可以使用 Request.Files進行獲得跟處理):
Response.Write("Post方式采用Request.Form[Name]:" + Request.Form["name"] + "</br>"); Response.Write("Post方式采用Request[Name]:" + Request["name"]);
在使用Post經常會無意中碰到一個錯誤:
解決方式(當runat="server"的表單通過修改action提交數據到其它頁面時,也會引發這個問題;把表單中的runat="server"去掉);
網上還有其它解決的辦法:
a:添加enableEventValidation="false" enableViewStateMac="false"或在webconfig中添加<pages enableEventValidation="false" enableViewStateMac="false" />
b:不使用跨頁面提交,提交到本頁后在page.load中redirect.
c:使用 <asp:Button runat="server" PostBackUrl="~/Register/DoRegister.aspx" Text="提交" />
4:平常通過Request獲得客戶端的Cookies值;
HttpCookie cookie = HttpContext.Current.Request.Cookies["HttpDemo"];
四:HttpContet對象之Response
1:Response理論知識:
Response代表了服務器響應對象。每次客戶端發出一個請求的時候,服務器就會用一個響應對象來處理這個請求,處理完這個請求之后,服務器就會銷毀這個相應對象,以便繼續接受其它客服端請求。
2:Response主要用來一些輸出的運用;只要簡單記住其幾個重要的屬性以及方法就差不多了;
protected void Button1_Click(object sender, EventArgs e) { Response.Redirect("Default.aspx"); } protected void Button2_Click(object sender, EventArgs e) { string FileContent = Server.MapPath(".") + "\\TextFile.txt"; Response.WriteFile(FileContent); } protected void Button3_Click(object sender, EventArgs e) { Response.Write("這是第一句"); Response.End(); //停止運行,不再執行任何語句 Response.Write("這是第二句"); Response.Clear(); //清空緩沖區中的所有內容輸出 Response.Close();//關閉當前服務器到客戶端的連接 }
Response還有個我們經常使用到的地方是針對下載文件時輸出時的內容:
public static void ResponseStream(Stream stream, string fileName) { if (stream.Length > 0) { try { long fileSize = stream.Length; System.Web.HttpContext.Current.Response.ContentType = "application/octet-stream"; //控制送出的文件類型 System.Web.HttpContext.Current.Response.AppendHeader("Content-Disposition", " attachment;filename=" + HttpUtility.UrlEncode(fileName, System.Text.Encoding.UTF8));//向響應輸出流增加HTTP頭信息 System.Web.HttpContext.Current.Response.AddHeader("Content-Length", fileSize.ToString()); byte[] fileBuffer = new byte[fileSize]; stream.Read(fileBuffer, 0, (int)fileSize); stream.Close(); System.Web.HttpContext.Current.Response.BinaryWrite(fileBuffer); System.Web.HttpContext.Current.Response.End(); } catch (Exception ex) { throw; } } }
針對Response.ContentType是表示送出的文件類型(下在我們列出一些比較常見的類型,其它類型可以到網絡上進行搜索):
'doc' => 'application/msword', 'bin' => 'application/octet-stream', 'exe' => 'application/octet-stream', 'dll' => 'application/octet-stream', 'pdf' => 'application/pdf', 'xls' => 'application/vnd.ms-excel', 'ppt' => 'application/vnd.ms-powerpoint', 'zip' => 'application/zip', 'mp3' => 'audio/mpeg', 'wav' => 'audio/x-wav', 'pdb' => 'chemical/x-pdb', 'bmp' => 'image/bmp', 'gif' => 'image/gif', 'ief' => 'image/ief', 'jpeg' => 'image/jpeg', 'jpg' => 'image/jpeg', 'jpe' => 'image/jpeg', 'png' => 'image/png',
另外當我們在寫入Cookies時通過Response的Set-Cookie向客戶端設置的Cookie;
HttpCookie ck = new HttpCookie("HttpDemo"); ck.Values.Add("UserID", "踏浪帥"); Response.SetCookie(ck); Response.Redirect("Default.aspx");
五:HttpContet對象之Sever
1:Server理論知識:
Server對象是用於獲取服務器的相關信息的對象
2:對於Server對象我們也是簡單的了解一些它的屬性內容;
StringBuilder strBuilder = new StringBuilder(); strBuilder.Append("獲取計算機名:"+HttpContext.Current.Server.MachineName+"</br>"); strBuilder.Append("獲取指定相對路徑在服務器上的物理路徑:" + Server.MapPath(".") + "</br>"); strBuilder.Append("在服務器里實現跳轉;不用再返回客戶端;Server.Transfer(string Path)</br>"); strBuilder.Append("先執行路徑所代表的URL,然后執行完之后再執行本頁:Server.Execute(string Path)</br>"); strBuilder.Append("對特殊字符串的處理:Server.HtmlDecode(string s)與Server.HtmlEncode(string s)</br>"); strBuilder.Append("對URL路徑字符串進行編解碼:Server.UrlDecode(string s)與Server.UrlEncode(string s)</br>"); Response.Write(strBuilder.ToString());
如果,您認為閱讀這篇博客讓您有些收獲,不妨點擊一下右下角的【推薦】按鈕。 因為,我的寫作熱情也離不開您的肯定支持。
感謝您的閱讀,[源代碼下載]
最近有個妹子弄的一個關於擴大眼界跟內含的訂閱號,每天都會更新一些深度內容,在這里如果你感興趣也可以關注一下(嘿對美女跟知識感興趣),當然可以關注后輸入:github 會有我的微信號,如果有問題你也可以在那找到我;當然不感興趣無視此信息;