※This article is based on .NET 7
ASP.NET Core应用开发中使用频率最高的对象。要说明HttpContext的本质,还得从请求处理管道的层面来讲。
对于由一个服务器和多个中间件构建的管道来说,面向传输层的服务器负责请求的监听、接收和最终的响应,当它接收到客户端发送的请求后,需要将它分发给后续中间件进行处理。
对于某个中间件来说,当我们完成了自身的请求处理任务之后,在大部分情况下也需要将请求分发给后续的中间件。请求在服务器与中间件之间,以及在中间件之间的分发是通过共享上下文的方式实现的。
当服务器接收到请求之后,会创建一个通过HttpContext表示的上下文对象,所有中间件都是在这个上下文中处理请求的,那么一个HttpContext对象究竟携带怎样的上下文信息呢?
我们知道一个HTTP事务(Transaction)具有非常清晰的界定,即接收请求、发送响应,所以请求和响应是两个基本的要素,也是HttpContext承载的最核心的上下文信息。
我们可以将请求理解为输入、响应理解为输出,所以应用程序可以利用HttpContext得到当前请求所有的输入信息,也可以利用它完成我们所需的所有输出工作。为此我们为ASP.NET Core Mini定义了如下这个极简版本的HttpContext。
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。通过前者,我们可以得到请求的地址、手部集合和主体内容,利用后者,我们可以设置响应状态码,也可以设置首部和主体内容。
在 ASP.NET Core 中要想得到 cookie 必须要有 Request 对象,要想得到 Request 对象 必须要有 HttpContext,要想得到 HttpContext 必须要利用 IHttpContextAccessor 接口
ASP.NET Core 中就内置了一个实现了该接口的 HttpContextAccessor 类
命名空间:Microsoft.AspNetCore.Http
程序集:Microsoft.AspNetCore.Http.Abstractions.dll
包:Microsoft.AspNetCore.App.Ref v7.0.5
public interface IHttpContextAccessor
{
HttpContext HttpContext { get; set; }
}
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
//IHttpContextAccessor register
services.AddHttpContextAccessor();
services.AddTransient<IUserService, UserService>();
}
将 IHttpContextAccessor 注入到创建的服务构造函数中,并访问 HttpContext 的属性,如下所示:
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
不直接使用父类 Controller 的 Request 和 HttpContext,这是因为此方式是一种强依赖,接下来给大家演示如何通过依赖注入的方式获取 HttpContext,此种更加灵活。
自定义一个Accessor
public class HttpContextAccessor : IHttpContextAccessor
{
public HttpContextAccessor();
public HttpContext HttpContext { get; set; }
}
为了实现依赖注入,需要将 IHttpContextAccessor 和 HttpContextAccessor 注入到 ServiceCollection 中,下面就用单例的模式进行注入
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IHttpContextAccessor,HttpContextAccessor>();
// 逻辑代码
}
然后就可以通过依赖注入的方式获取 IHttpContextAccessor 接口的实例,再依次获取 HttpContext 对象,下面的代码片段展示了如何在 Controller 中访问 IHttpContextAccessor 实例
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");
}
}
public IActionResult Read(string key)
{
ViewBag.Data = _httpContextAccessor.HttpContext.Request.Cookies[key];
return View("ReadCookie");
}
コメント: