将 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:
- public class HomeController : Controller
- {
- private readonly ILogger<HomeController> _logger;
- private string customer;
- public HomeController(ILogger<HomeController> logger)
- {
- _logger = logger;
- customer = HttpContext.Request.Form["CustomerId"];
- }
- }
三, 在中间件中使用 HttpContext
自定义扩展中间件中, 实现 Invoke 方法, HttpContext 通过参数的方式传递到中间件的业务逻辑中.
- public async Task Invoke(HttpContext context)
- public class CustomerMiddleware
- {
- private readonly RequestDelegate _next;
- public CustomerMiddleware(RequestDelegate next)
- {
- _next = next;
- }
- public async Task Invoke(HttpContext context)
- {
- // Do something with context near the beginning of request processing.
- await _next.Invoke(context);
- // Clean up.
- }
- }
四. 在数据访问层使用 HttpContext
声明一个 User 的仓储类, 实现对 User 的持久化. 如下代码中,
UserRepository 依赖 IHttpContextAccessor
通过 ASP.NET Core 依赖注入容器解析依赖链并创建 UserRepository 实例时, 就会注入依赖项.
- public class UserRepository: IUserRepository
- {
- private readonly IHttpContextAccessor _httpContextAccessor;
- public UserRepository(IHttpContextAccessor httpContextAccessor)
- {
- _httpContextAccessor = httpContextAccessor;
- }
- public void AddUser(User user)
- {
- var username = _httpContextAccessor.HttpContext.User.Identity.Name;
- //Save User to DB
- }
- }
使用 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 的访问, 如下代码:
- public class UserModel: PageModel
- {
- public string Message { get; set; }
- public void OnGet()
- {
- Message = HttpContext.Request.PathBase;
- }
- }
七, 在 Razor 视图中访问 HttpContext
Razor 视图通过视图上的 RazorPage.Context 属性直接公开 HttpContext
- @{
- ViewData["Title"] = "Home Page";
- var username = Context.User.Identity.Name;
- }
以上是近期总结的 6 种 HttpContext 访问的正确姿势. 详细参考了以下链接:
分享给大家.
周国庆
2020/3/25
来源: https://www.cnblogs.com/tianqing/p/12570801.html