91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

HttpContext.Current實例分析

發布時間:2022-03-31 16:43:22 來源:億速云 閱讀:345 作者:iii 欄目:編程語言

本篇內容主要講解“HttpContext.Current實例分析”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“HttpContext.Current實例分析”吧!

無處不在的HttpContext

由于ASP.NET提供了靜態屬性HttpContext.Current,因此獲取HttpContext對象就非常方便了。也正是因為這個原因,所以我們經常能見到直接訪問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"];      }       // 甚至還設計成靜態屬性      public static string XXX      {          get         {              return (string)HttpContext.Current.Items["XXX"];          }      }  }

這樣的代碼,經常能在類庫項目中看到,由此可見其泛濫程度。

難道這些代碼真的沒有問題嗎?

有人估計會說:我寫的代碼是給ASP.NET程序使用的,又不是給控制臺程序使用,所以沒有問題。

真的是這樣嗎?

HttpContext.Current到底保存在哪里?

的確,在一個ASP.NET程序中,幾乎任何時候,我們都可以訪問HttpContext.Current得到一個HttpContext對象,然而,您有沒有想過它是如何實現的呢?

如果您沒有想過這個事情,那我今天就來告訴您吧。請看下面的代碼

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);  }

猜猜會顯示什么?

HttpContext.Current實例分析

這就是我看到的結果,不信的話您也可以試試。

從這段代碼來看,HttpContext其實是保存在CallContext.HostContext這個屬性中,如果您還對HostContext感到好奇的話,您可以自己用Reflector.exe去看,我不想再貼代碼了,因為有些類型和方法并不是公開的。

我們還是來看看MSDN是如何解釋CallContext.HostContext的吧:

獲取或設置與當前線程相關聯的主機上下文。

這個解釋非常含糊,不過有二個關鍵詞我們可以記下來:【當前線程】,【關聯】。

是說:和當前線程相關聯的某個東西嗎?

我是這樣理解的。

我們在一個ASP.NET程序中,為什么可以到處訪問HttpContext.Current呢?

因為ASP.NET會為每個請求分配一個線程,這個線程會執行我們的代碼來生成響應結果,即使我們的代碼散落在不同的地方(類庫),線程仍然會執行它們,所以,我們可以在任何地方訪問HttpContext.Current獲取到與【當前請求】相關的HttpContext對象,畢竟這些代碼是由同一個線程來執行的嘛,所以得到的HttpContext引用也就是我們期待的那個與請求相關的對象。

因此,將HttpContext.Current設計成與【當前線程】相關聯是合適的。

HttpContext并非無處不在!

【當前線程】是個什么意思? 我為什么要突出這個詞呢?

答:

1. 當前線程是指與【當前請求】相關的線程。

2. 在ASP.NET中,有些線程并非總是與請求相關。

感覺有點繞口嗎? 不容易理解嗎? 還是繼續往下看吧。

雖然在ASP.NET程序中,幾乎所有的線程都應該是為響應請求而運行的,

但是,還有一些線程卻不是為了響應請求而運行,例如:

1. 定時器的回調。

2. Cache的移除通知。

3. APM模式下異步完成回調。

4. 主動創建線程或者將任務交給線程池來執行。

在以上這些情況中,如果線程執行到HttpContext.Current,您認為會返回什么?

還是一個HttpContext的實例引用嗎?

如何是,那它與哪個請求關聯?

顯然,在1,2二種情況中,訪問HttpContext.Current將會返回 null 。

因為很有可能任務在運行時根本沒有任何請求發生。了解異步的人應該能很容易理解第3種情況(就當是個結論吧)

第4種情況就更不需要解釋了,因為確實不是當前線程。

既然是這樣,那我們再看一下本文開頭的一段代碼:

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

想像一下:如果Class1是在定時器回調或者Cache的移除通知時被創建的,您認為它還能正常運行嗎?

此刻您心里應該有答案了吧?

可能您會想:為什么我在其它任何地方又可以訪問HttpContext.Current得到HttpContext引用呢?

答:那是因為ASP.NET在調用您的代碼前,已經將HttpContext設置到前面所說的CallContext.HostContext屬性中。

HttpApplication有個內部方法OnThreadEnter(),ASP.NET在調用外部代碼前會調用這個方法來切換HttpContext,例如:每當執行管線的事件處理器之前,或者同步上下文(AspNetSynchronizationContext)執行回調時。切換線程的CallContext.HostContext屬性之后,我們的代碼就可以訪問到HttpContext引用。注意:HttpContext的引用其實是保存在HttpApplication對象中。

有時候我們會見到【ASP.NET線程】這個詞,今天正好來說說我對這個詞的理解:當前線程是與一個HttpContext相關的線程,由于線程與HttpContext相關聯,也就意味著它正在處理發送給ASP.NET的請求。注意:這個線程仍然是線程池的線程。

如何獲取文件絕對路徑?

在定時器回調或者Cache的移除通知中,有時確實需要訪問文件,然而對于開發人員來說,他們并不知道網站會被部署在哪個目錄下,因此不可能寫出絕對路徑,他們只知道相對于網站根目錄的相對路徑,為了定位文件路徑,只能調用HttpContext.Current.Request.MapPath或者 HttpContext.Current.Server.MapPath來獲取文件的絕對路徑。如果HttpContext.Current返回了null,那該如何如何訪問文件?

其實方法并非MapPath一種,我們可以訪問HttpRuntime.AppDomainAppPath獲取網站的路徑,然后再拼接文件的相對路徑即可:

HttpContext.Current實例分析

看到沒:圖片中HttpContext.Current顯示的是 null ,所以您要是再調用MapPath,就必死無疑!

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

異步調用中如何訪問HttpContext?

前面我還提到在APM模式下的異步完成回調時,訪問HttpContext.Current也會返回null,那么此時該怎么辦呢?

答案有二種:

1. 在類型中添加一個字段來保存HttpContext的引用(異步開始前)。

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

建議優先選擇第二種方法,因為可以防止以后他人維護時數據成員被意外使用。

安全地使用HttpContext.Current

有時我們會寫些通用類庫給ASP.NET或者WindowsService程序來使用,例如異常記錄的工具方法。對于ASP.NET程序來說,我們肯定希望在異常發生時,能記錄URL,表單值,Cookie等等數據,便于事后分析。然而對于WindowsService這類程序來說,您肯定沒想過要記錄Cookie吧?那么如何實現一個通用的功能呢?

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

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

就是一個判斷,解決了所有問題,所以請忘記下面這類不安全的寫法吧:

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

下面的方法才是安全的:

HttpContext context = HttpContext.Current;  if( context != null ) {      // 在這里訪問與請求有關的東西。  }

到此,相信大家對“HttpContext.Current實例分析”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

西和县| 丹凤县| 台中县| 洪湖市| 郓城县| 顺平县| 中西区| 邳州市| 神木县| 元氏县| 定陶县| 石渠县| 同心县| 淮安市| 柞水县| 乌鲁木齐市| 涿州市| 天台县| 鸡西市| 麻城市| 大悟县| 新密市| 池州市| 南安市| 东台市| 巴马| 达尔| 雅江县| 洛南县| 青田县| 赞皇县| 虞城县| 绩溪县| 筠连县| 张家界市| 五台县| 古蔺县| 南安市| 泸水县| 新乡市| 永登县|