將ASP.NET升級到ASP.NET Core之后,相信大家都會遇到HttpContext.Current無法使用的問題。這也是我們遷移ASP.NET Core必須解決的問題。
本文我們詳細討論一下,使用HttpContext的正確姿勢。
先列一下使用HttpContext的具體場景:
1. 在Controller層訪問HttpContext
2. 在中間件中使用HttpContext
3. 在數據訪問層使用HttpContext
4. 在后台線程中訪問HttpContext
5. 在Razor頁面模型中訪問HttpContext
6. 在Razor視圖中訪問HttpContext
可能還有其他的應用場景。接下來我們按場景一一示例解決。
首先本文用的是ASP.NET Core 3.1
一、新建一個ASP.NET Core Web應用程序
二、在Controller層訪問HttpContext
示例代碼中HomeController繼承與Controller抽象類
Controller父類中繼承與ControllerBase抽象類
其中ControllerBase抽象類有提供了對HttpContext的訪問
所以,我們在Controller這一層可以按以下方式訪問HttpContext:
1 public class HomeController : Controller 2 { 3 private readonly ILogger<HomeController> _logger; 4 private string customer; 5 6 public HomeController(ILogger<HomeController> logger) 7 { 8 _logger = logger; 9 10 customer = HttpContext.Request.Form["CustomerId"]; 11 } 12 }
三、在中間件中使用HttpContext
自定義擴展中間件中,實現Invoke方法,HttpContext通過參數的方式傳遞到中間件的業務邏輯中。
public async Task Invoke(HttpContext context)
1 public class CustomerMiddleware 2 { 3 private readonly RequestDelegate _next; 4 5 public CustomerMiddleware(RequestDelegate next) 6 { 7 _next = next; 8 } 9 10 public async Task Invoke(HttpContext context) 11 { 12 // Do something with context near the beginning of request processing. 13 await _next.Invoke(context); 14 15 // Clean up. 16 } 17 }
四. 在數據訪問層使用HttpContext
聲明一個User的倉儲類,實現對User的持久化。如下代碼中,
UserRepository依賴 IHttpContextAccessor
通過ASP.NET Core依賴注入容器解析依賴鏈並創建 UserRepository 實例時,就會注入依賴項。
1 public class UserRepository: IUserRepository 2 { 3 private readonly IHttpContextAccessor _httpContextAccessor; 4 5 public UserRepository(IHttpContextAccessor httpContextAccessor) 6 { 7 _httpContextAccessor = httpContextAccessor; 8 } 9 10 public void AddUser(User user) 11 { 12 var username = _httpContextAccessor.HttpContext.User.Identity.Name; 13 14 //Save User to DB 15 } 16 }
使用ASP.NET Core內置的依賴項注入容器來注冊依賴項。 依賴項注入容器向任意類提供 IHttpContextAccessor,以供類在自己的構造函數中將它聲明為依賴項:
public void ConfigureServices(IServiceCollection services) { services.AddControllersWithViews(); services.AddHttpContextAccessor(); services.AddTransient<IUserRepository, UserRepository>(); }
五、在后台線程中訪問HttpContext
HttpContext 不是線程安全的。 在處理請求之外讀取或寫入 HttpContext 的屬性,可能會導致 NullReferenceException空引用異常。
如何再后台線程中使用HttpContext呢?推薦的做法:
1. 在請求處理過程中復制所需的數據。
2. 將復制的數據傳遞給后台任務。
六、在Razor頁面模型中訪問HttpContext
Razor頁面模型的父類PageModel提供了HttpContext的訪問,如下代碼:
1 public class UserModel: PageModel 2 { 3 public string Message { get; set; } 4 5 public void OnGet() 6 { 7 Message = HttpContext.Request.PathBase; 8 } 9 }
七、 在Razor視圖中訪問HttpContext
Razor 視圖通過視圖上的 RazorPage.Context 屬性直接公開 HttpContext
@{
ViewData["Title"] = "Home Page"; var username = Context.User.Identity.Name; }