#author("2023-11-20T19:17:30+08:00","default:Admin","Admin") #author("2023-11-25T17:29:24+08:00","default:Admin","Admin") [[ASP.NET Core Web]] &color(red){※This article is based on .NET 7}; #contents * 概要 [#t17da002] ASP.NET Core应用开发中使用频率最高的对象。要说明HttpContext的本质,还得从请求处理管道的层面来讲。 对于由一个服务器和多个中间件构建的管道来说,面向传输层的服务器负责请求的监听、接收和最终的响应,当它接收到客户端发送的请求后,需要将它分发给后续中间件进行处理。 对于某个中间件来说,当我们完成了自身的请求处理任务之后,在大部分情况下也需要将请求分发给后续的中间件。请求在服务器与中间件之间,以及在中间件之间的分发是通过共享上下文的方式实现的。 当服务器接收到请求之后,会创建一个通过HttpContext表示的上下文对象,所有中间件都是在这个上下文中处理请求的,那么一个HttpContext对象究竟携带怎样的上下文信息呢? * 举例 [#redf85ec] 我们知道一个HTTP事务(Transaction)具有非常清晰的界定,即接收请求、发送响应,所以请求和响应是两个基本的要素,也是HttpContext承载的最核心的上下文信息。 我们可以将请求理解为输入、响应理解为输出,所以应用程序可以利用HttpContext得到当前请求所有的输入信息,也可以利用它完成我们所需的所有输出工作。为此我们为ASP.NET Core Mini定义了如下这个极简版本的HttpContext。 #codeprettify{{ public class HttpContext { public HttpRequest Request { get; } public HttpResponse Response { get; } } public class HttpRequest { public Uri Url { get; } public NameValueCollection Headers { get; } public Stream Body { get; } } public class HttpResponse { public NameValueCollection Headers { get; } public Stream Body { get; } public int StatusCode { get; set;} } }} 如上面的代码片段所示,HttpContext通过它的两个属性Request和Response来表示请求和响应,它们对应的类型分别为HttpRequest和HttpResponse。通过前者,我们可以得到请求的地址、手部集合和主体内容,利用后者,我们可以设置响应状态码,也可以设置首部和主体内容。 * 调用HttpContext [#jeacfe70] 在 ASP.NET Core 中要想得到 cookie 必须要有 Request 对象,要想得到 Request 对象 必须要有 HttpContext,要想得到 HttpContext 必须要利用 IHttpContextAccessor 接口 ASP.NET Core 中就内置了一个实现了该接口的 HttpContextAccessor 类 #codeprettify{{ 命名空间:Microsoft.AspNetCore.Http 程序集:Microsoft.AspNetCore.Http.Abstractions.dll 包:Microsoft.AspNetCore.App.Ref v7.0.5 public interface IHttpContextAccessor { HttpContext HttpContext { get; set; } } }} ** 内置标准方法 [#g6a0f201] *** 依赖注入 [#e5df9b70] #codeprettify{{ public void ConfigureServices(IServiceCollection services) { services.AddControllers(); //IHttpContextAccessor register services.AddHttpContextAccessor(); services.AddTransient<IUserService, UserService>(); } }} *** 使用 [#s31e91fc] 将 IHttpContextAccessor 注入到创建的服务构造函数中,并访问 HttpContext 的属性,如下所示: #codeprettify{{ namespace Get_HttpContext_ASP.NET_Core { using Microsoft.AspNetCore.Http; public class UserService : IUserService { private readonly IHttpContextAccessor _httpContextAccessor; public UserService(IHttpContextAccessor httpContextAccessor) { _httpContextAccessor = httpContextAccessor; } public string GetLoginUserName() { return _httpContextAccessor.HttpContext.User.Identity.Name; } } } }} https://www.telerik.com/blogs/how-to-get-httpcontext-asp-net-core ** 进阶方法 [#k9f6840f] 不直接使用父类 Controller 的 Request 和 HttpContext,这是因为此方式是一种强依赖,接下来给大家演示如何通过依赖注入的方式获取 HttpContext,此种更加灵活。 *** 依赖注入 [#p3c9741a] 自定义一个Accessor #codeprettify{{ public class HttpContextAccessor : IHttpContextAccessor { public HttpContextAccessor(); public HttpContext HttpContext { get; set; } } }} 为了实现依赖注入,需要将 IHttpContextAccessor 和 HttpContextAccessor 注入到 ServiceCollection 中,下面就用单例的模式进行注入 #codeprettify{{ public void ConfigureServices(IServiceCollection services) { services.AddSingleton<IHttpContextAccessor,HttpContextAccessor>(); // 逻辑代码 } }} 如果提示下面的报错,也是因为HttpContextAccessor没有注入导致的 Microsoft.AspNetCore.Authorization.Policy.PolicyEvaluator': Unable to resolve service for type 'Microsoft.AspNetCore.Http.HttpContextAccessor' while attempting to activate *** 写入 [#ceb1e433] 然后就可以通过依赖注入的方式获取 IHttpContextAccessor 接口的实例,再依次获取 HttpContext 对象,下面的代码片段展示了如何在 Controller 中访问 IHttpContextAccessor 实例 #codeprettify{{ public class HomeController : Controller { private readonly IHttpContextAccessor _httpContextAccessor; public HomeController(IHttpContextAccessor httpContextAccessor) { this._httpContextAccessor = httpContextAccessor; } //写入Cookie public IActionResult Write(string key, string value, bool isPersistent) { CookieOptions options = new CookieOptions(); if (isPersistent) options.Expires = DateTime.Now.AddDays(1); else options.Expires = DateTime.Now.AddSeconds(10); _httpContextAccessor.HttpContext.Response.Cookies.Append(key, value, options); return View("WriteCookie"); } } }} *** 读取 [#cac81576] #codeprettify{{ public IActionResult Read(string key) { ViewBag.Data = _httpContextAccessor.HttpContext.Request.Cookies[key]; return View("ReadCookie"); } }} #hr(); コメント: #comment_kcaptcha