真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

HttpContext.Current實(shí)例分析

本篇內(nèi)容主要講解“HttpContext.Current實(shí)例分析”,感興趣的朋友不妨來(lái)看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來(lái)帶大家學(xué)習(xí)“HttpContext.Current實(shí)例分析”吧!

創(chuàng)新互聯(lián)建站是專(zhuān)業(yè)的內(nèi)蒙古網(wǎng)站建設(shè)公司,內(nèi)蒙古接單;提供成都網(wǎng)站建設(shè)、網(wǎng)站設(shè)計(jì),網(wǎng)頁(yè)設(shè)計(jì),網(wǎng)站設(shè)計(jì),建網(wǎng)站,PHP網(wǎng)站建設(shè)等專(zhuān)業(yè)做網(wǎng)站服務(wù);采用PHP框架,可快速的進(jìn)行內(nèi)蒙古網(wǎng)站開(kāi)發(fā)網(wǎng)頁(yè)制作和功能擴(kuò)展;專(zhuān)業(yè)做搜索引擎喜愛(ài)的網(wǎng)站,專(zhuān)業(yè)的做網(wǎng)站團(tuán)隊(duì),希望更多企業(yè)前來(lái)合作!

無(wú)處不在的HttpContext

由于A(yíng)SP.NET提供了靜態(tài)屬性HttpContext.Current,因此獲取HttpContext對(duì)象就非常方便了。也正是因?yàn)檫@個(gè)原因,所以我們經(jīng)常能見(jiàn)到直接訪(fǎng)問(wèn)HttpContext.Current的代碼:

public class Class1  {      public Class1()      {          string file = HttpContext.Current.Request.MapPath("~/App_Data/xxxxxx.xml");           string text = System.IO.File.ReadAllText(file);           //..........其它的操作      }       // 或者在一些方法中直接使用HttpContext.Current      public void XXXXX()      {          string url = HttpContext.Current.Request.RawUrl;           string username = HttpContext.Current.Session["username"].ToString();           string value = (string)HttpContext.Current.Items["key"];      }       // 甚至還設(shè)計(jì)成靜態(tài)屬性      public static string XXX      {          get         {              return (string)HttpContext.Current.Items["XXX"];          }      }  }

這樣的代碼,經(jīng)常能在類(lèi)庫(kù)項(xiàng)目中看到,由此可見(jiàn)其泛濫程度。

難道這些代碼真的沒(méi)有問(wèn)題嗎?

有人估計(jì)會(huì)說(shuō):我寫(xiě)的代碼是給ASP.NET程序使用的,又不是給控制臺(tái)程序使用,所以沒(méi)有問(wèn)題。

真的是這樣嗎?

HttpContext.Current到底保存在哪里?

的確,在一個(gè)ASP.NET程序中,幾乎任何時(shí)候,我們都可以訪(fǎng)問(wèn)HttpContext.Current得到一個(gè)HttpContext對(duì)象,然而,您有沒(méi)有想過(guò)它是如何實(shí)現(xiàn)的呢?

如果您沒(méi)有想過(guò)這個(gè)事情,那我今天就來(lái)告訴您吧。請(qǐng)看下面的代碼

protected void Page_Load(object sender, EventArgs e)  {      HttpContext context1 = HttpContext.Current;       HttpContext context2 = System.Runtime.Remoting.Messaging.CallContext.HostContext as HttpContext;       bool isEqual = object.ReferenceEquals(context1, context2);       Response.Write(isEqual);  }

猜猜會(huì)顯示什么?

HttpContext.Current實(shí)例分析

這就是我看到的結(jié)果,不信的話(huà)您也可以試試。

從這段代碼來(lái)看,HttpContext其實(shí)是保存在CallContext.HostContext這個(gè)屬性中,如果您還對(duì)HostContext感到好奇的話(huà),您可以自己用Reflector.exe去看,我不想再貼代碼了,因?yàn)橛行╊?lèi)型和方法并不是公開(kāi)的。

我們還是來(lái)看看MSDN是如何解釋CallContext.HostContext的吧:

獲取或設(shè)置與當(dāng)前線(xiàn)程相關(guān)聯(lián)的主機(jī)上下文。

這個(gè)解釋非常含糊,不過(guò)有二個(gè)關(guān)鍵詞我們可以記下來(lái):【當(dāng)前線(xiàn)程】,【關(guān)聯(lián)】。

是說(shuō):和當(dāng)前線(xiàn)程相關(guān)聯(lián)的某個(gè)東西嗎?

我是這樣理解的。

我們?cè)谝粋€(gè)ASP.NET程序中,為什么可以到處訪(fǎng)問(wèn)HttpContext.Current呢?

因?yàn)锳SP.NET會(huì)為每個(gè)請(qǐng)求分配一個(gè)線(xiàn)程,這個(gè)線(xiàn)程會(huì)執(zhí)行我們的代碼來(lái)生成響應(yīng)結(jié)果,即使我們的代碼散落在不同的地方(類(lèi)庫(kù)),線(xiàn)程仍然會(huì)執(zhí)行它們,所以,我們可以在任何地方訪(fǎng)問(wèn)HttpContext.Current獲取到與【當(dāng)前請(qǐng)求】相關(guān)的HttpContext對(duì)象,畢竟這些代碼是由同一個(gè)線(xiàn)程來(lái)執(zhí)行的嘛,所以得到的HttpContext引用也就是我們期待的那個(gè)與請(qǐng)求相關(guān)的對(duì)象。

因此,將HttpContext.Current設(shè)計(jì)成與【當(dāng)前線(xiàn)程】相關(guān)聯(lián)是合適的。

HttpContext并非無(wú)處不在!

【當(dāng)前線(xiàn)程】是個(gè)什么意思? 我為什么要突出這個(gè)詞呢?

答:

1. 當(dāng)前線(xiàn)程是指與【當(dāng)前請(qǐng)求】相關(guān)的線(xiàn)程。

2. 在A(yíng)SP.NET中,有些線(xiàn)程并非總是與請(qǐng)求相關(guān)。

感覺(jué)有點(diǎn)繞口嗎? 不容易理解嗎? 還是繼續(xù)往下看吧。

雖然在A(yíng)SP.NET程序中,幾乎所有的線(xiàn)程都應(yīng)該是為響應(yīng)請(qǐng)求而運(yùn)行的,

但是,還有一些線(xiàn)程卻不是為了響應(yīng)請(qǐng)求而運(yùn)行,例如:

1. 定時(shí)器的回調(diào)。

2. Cache的移除通知。

3. APM模式下異步完成回調(diào)。

4. 主動(dòng)創(chuàng)建線(xiàn)程或者將任務(wù)交給線(xiàn)程池來(lái)執(zhí)行。

在以上這些情況中,如果線(xiàn)程執(zhí)行到HttpContext.Current,您認(rèn)為會(huì)返回什么?

還是一個(gè)HttpContext的實(shí)例引用嗎?

如何是,那它與哪個(gè)請(qǐng)求關(guān)聯(lián)?

顯然,在1,2二種情況中,訪(fǎng)問(wèn)HttpContext.Current將會(huì)返回 null 。

因?yàn)楹苡锌赡苋蝿?wù)在運(yùn)行時(shí)根本沒(méi)有任何請(qǐng)求發(fā)生。了解異步的人應(yīng)該能很容易理解第3種情況(就當(dāng)是個(gè)結(jié)論吧)

第4種情況就更不需要解釋了,因?yàn)榇_實(shí)不是當(dāng)前線(xiàn)程。

既然是這樣,那我們?cè)倏匆幌卤疚拈_(kāi)頭的一段代碼:

public Class1()  {      string file = HttpContext.Current.Request.MapPath("~/App_Data/xxxxxx.xml");       string text = System.IO.File.ReadAllText(file);       //..........其它的操作  }

想像一下:如果Class1是在定時(shí)器回調(diào)或者Cache的移除通知時(shí)被創(chuàng)建的,您認(rèn)為它還能正常運(yùn)行嗎?

此刻您心里應(yīng)該有答案了吧?

可能您會(huì)想:為什么我在其它任何地方又可以訪(fǎng)問(wèn)HttpContext.Current得到HttpContext引用呢?

答:那是因?yàn)锳SP.NET在調(diào)用您的代碼前,已經(jīng)將HttpContext設(shè)置到前面所說(shuō)的CallContext.HostContext屬性中。

HttpApplication有個(gè)內(nèi)部方法OnThreadEnter(),ASP.NET在調(diào)用外部代碼前會(huì)調(diào)用這個(gè)方法來(lái)切換HttpContext,例如:每當(dāng)執(zhí)行管線(xiàn)的事件處理器之前,或者同步上下文(AspNetSynchronizationContext)執(zhí)行回調(diào)時(shí)。切換線(xiàn)程的CallContext.HostContext屬性之后,我們的代碼就可以訪(fǎng)問(wèn)到HttpContext引用。注意:HttpContext的引用其實(shí)是保存在HttpApplication對(duì)象中。

有時(shí)候我們會(huì)見(jiàn)到【ASP.NET線(xiàn)程】這個(gè)詞,今天正好來(lái)說(shuō)說(shuō)我對(duì)這個(gè)詞的理解:當(dāng)前線(xiàn)程是與一個(gè)HttpContext相關(guān)的線(xiàn)程,由于線(xiàn)程與HttpContext相關(guān)聯(lián),也就意味著它正在處理發(fā)送給ASP.NET的請(qǐng)求。注意:這個(gè)線(xiàn)程仍然是線(xiàn)程池的線(xiàn)程。

如何獲取文件絕對(duì)路徑?

在定時(shí)器回調(diào)或者Cache的移除通知中,有時(shí)確實(shí)需要訪(fǎng)問(wèn)文件,然而對(duì)于開(kāi)發(fā)人員來(lái)說(shuō),他們并不知道網(wǎng)站會(huì)被部署在哪個(gè)目錄下,因此不可能寫(xiě)出絕對(duì)路徑,他們只知道相對(duì)于網(wǎng)站根目錄的相對(duì)路徑,為了定位文件路徑,只能調(diào)用HttpContext.Current.Request.MapPath或者 HttpContext.Current.Server.MapPath來(lái)獲取文件的絕對(duì)路徑。如果HttpContext.Current返回了null,那該如何如何訪(fǎng)問(wèn)文件?

其實(shí)方法并非MapPath一種,我們可以訪(fǎng)問(wèn)HttpRuntime.AppDomainAppPath獲取網(wǎng)站的路徑,然后再拼接文件的相對(duì)路徑即可:

HttpContext.Current實(shí)例分析

看到?jīng)]:圖片中HttpContext.Current顯示的是 null ,所以您要是再調(diào)用MapPath,就必死無(wú)疑!

在此我也奉勸大家一句:盡量不要用MapPath,HttpRuntime.AppDomainAppPath才是更安全的選擇。

異步調(diào)用中如何訪(fǎng)問(wèn)HttpContext?

前面我還提到在A(yíng)PM模式下的異步完成回調(diào)時(shí),訪(fǎng)問(wèn)HttpContext.Current也會(huì)返回null,那么此時(shí)該怎么辦呢?

答案有二種:

1. 在類(lèi)型中添加一個(gè)字段來(lái)保存HttpContext的引用(異步開(kāi)始前)。

2. 將HttpContext賦值給BeginXXX方法的最后一個(gè)參數(shù)(object state)

建議優(yōu)先選擇第二種方法,因?yàn)榭梢苑乐挂院笏司S護(hù)時(shí)數(shù)據(jù)成員被意外使用。

安全地使用HttpContext.Current

有時(shí)我們會(huì)寫(xiě)些通用類(lèi)庫(kù)給ASP.NET或者WindowsService程序來(lái)使用,例如異常記錄的工具方法。對(duì)于A(yíng)SP.NET程序來(lái)說(shuō),我們肯定希望在異常發(fā)生時(shí),能記錄URL,表單值,Cookie等等數(shù)據(jù),便于事后分析。然而對(duì)于WindowsService這類(lèi)程序來(lái)說(shuō),您肯定沒(méi)想過(guò)要記錄Cookie吧?那么如何實(shí)現(xiàn)一個(gè)通用的功能呢?

方法其實(shí)也簡(jiǎn)單,就是要判斷HttpContext.Current是否返回null,例如下面的示例代碼:

public static void LogException(Exception ex)  {      StringBuilder sb = new StringBuilder();      sb.Append("異常發(fā)生時(shí)間:").AppendLine(DateTime.Now.ToString());      sb.AppendLine(ex.ToString());       // 如果是ASP.NET程序,還需要記錄URL,F(xiàn)ORM, COOKIE之類(lèi)的數(shù)據(jù)      HttpContext context = HttpContext.Current;      if( context != null ) {          // 能運(yùn)行到這里,就肯定是在處理ASP.NET請(qǐng)求,我們可以放心地訪(fǎng)問(wèn)Request的所有數(shù)據(jù)          sb.AppendLine("Url:" + context.Request.RawUrl);           // 還有記錄什么數(shù)據(jù),您自己來(lái)實(shí)現(xiàn)吧。      }       System.IO.File.AppendAllText("日志文件路徑", sb.ToString());  }

就是一個(gè)判斷,解決了所有問(wèn)題,所以請(qǐng)忘記下面這類(lèi)不安全的寫(xiě)法吧:

HttpContext.Current.Request.RawUrl;  HttpContext.Current.Server.MapPath("xxxxxx");

下面的方法才是安全的:

HttpContext context = HttpContext.Current;  if( context != null ) {      // 在這里訪(fǎng)問(wèn)與請(qǐng)求有關(guān)的東西。  }

到此,相信大家對(duì)“HttpContext.Current實(shí)例分析”有了更深的了解,不妨來(lái)實(shí)際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢(xún),關(guān)注我們,繼續(xù)學(xué)習(xí)!


標(biāo)題名稱(chēng):HttpContext.Current實(shí)例分析
網(wǎng)站網(wǎng)址:http://weahome.cn/article/gecssp.html

其他資訊

在線(xiàn)咨詢(xún)

微信咨詢(xún)

電話(huà)咨詢(xún)

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部