构造函数中的 HttpContext null
HttpContext null in constructor
我有一个 UserContext 服务,我将在其中放置一些基本功能(IsAuthenticated
、GetUser
等...)
为此,我需要将 HTTPContext
从我的 WebAPI 控制器传递到我的 Class 图书馆服务。
实际上,HttpContext
在网络 api 控制器中总是 null
。
有人有办法解决我的问题吗?。
有没有更好的实现方式呢
Web API 用户控制器
[Route("api/[controller]")]
[Authorize]
public class UserController : Controller
{
private readonly IUserContextServices _userContextServices;
private readonly User loggedUser;
public UserController()
{
//HttpContext ALWAYS NULL
_userContextServices = new UserContextService(HttpContext);
}
}
UserContext 服务
namespace MyProj.Services
{
public interface IUserContextServices
{
UserContext GetUserContext();
bool IsUserAuthenticated();
}
public class UserContextService : IUserContextServices
{
private readonly HttpContext _context;
private UserContext _userContext;
public UserContextService(HttpContext context)
{
_context = context;
InitUserContext();
}
private IEnumerable<Claim> GetUserClaims()
{
if (IsUserAuthenticated())
{
return _context.User.Claims;
}
return null;
}
private void InitUserContext()
{
if (IsUserAuthenticated())
{
var claims = GetUserClaims();
_userContext = new UserContext();
_userContext.Email = claims.First(p => p.Type == "email").Value;
_userContext.AspNetUserID = claims.First(p => p.Type == "sub").Value;
}
}
public UserContext GetUserContext()
{
return _userContext;
}
public bool IsUserAuthenticated()
{
return _context.User != null && _context.User.Identity != null && _context.User.Identity.IsAuthenticated;
}
}
}
HttpContext
在调用Controller的构造函数时不可用。您将不得不重新设计代码,以便稍后在调用流程中获取上下文。这就是 IHttpContextAccessor
的用途。
public interface IHttpContextAccessor {
HttpContext HttpContext { get; }
}
将其注入服务,然后根据需要访问上下文。
public class UserContextService : IUserContextServices {
private readonly IHttpContextAccessor contextAccessor;
private UserContext _userContext;
public UserContextService(IHttpContextAccessor accessor) {
contextAccessor = accessor;
}
private HttpContext Context {
get {
return contextAccessor.HttpContext;
}
}
public UserContext GetUserContext() {
if (_userContext == null && IsUserAuthenticated()) {
var claims = Context?.User?.Claims;
_userContext = new UserContext() {
Email = claims.First(p => p.Type == "email").Value,
AspNetUserID = claims.First(p => p.Type == "sub").Value
};
}
return _userContext;
}
public bool IsUserAuthenticated() {
return Context?.User?.Identity?.IsAuthenticated;
}
}
将服务抽象注入控制器
[Route("api/[controller]")]
[Authorize]
public class UserController : Controller {
private readonly IUserContextServices _userContextServices;
private readonly User loggedUser;
public UserController(IUserContextServices userContextServices) {
_userContextServices = userContextServices;
}
//...
}
IHttpContextAccessor
默认情况下不在服务集合中,因此您需要手动将其添加到 Startup.ConfigureServices
中以便能够注入它:
services.AddHttpContextAccessor();
services.AddTransient<IUserContextServices, UserContextService>();
我有一个 UserContext 服务,我将在其中放置一些基本功能(IsAuthenticated
、GetUser
等...)
为此,我需要将 HTTPContext
从我的 WebAPI 控制器传递到我的 Class 图书馆服务。
实际上,HttpContext
在网络 api 控制器中总是 null
。
有人有办法解决我的问题吗?。 有没有更好的实现方式呢
Web API 用户控制器
[Route("api/[controller]")]
[Authorize]
public class UserController : Controller
{
private readonly IUserContextServices _userContextServices;
private readonly User loggedUser;
public UserController()
{
//HttpContext ALWAYS NULL
_userContextServices = new UserContextService(HttpContext);
}
}
UserContext 服务
namespace MyProj.Services
{
public interface IUserContextServices
{
UserContext GetUserContext();
bool IsUserAuthenticated();
}
public class UserContextService : IUserContextServices
{
private readonly HttpContext _context;
private UserContext _userContext;
public UserContextService(HttpContext context)
{
_context = context;
InitUserContext();
}
private IEnumerable<Claim> GetUserClaims()
{
if (IsUserAuthenticated())
{
return _context.User.Claims;
}
return null;
}
private void InitUserContext()
{
if (IsUserAuthenticated())
{
var claims = GetUserClaims();
_userContext = new UserContext();
_userContext.Email = claims.First(p => p.Type == "email").Value;
_userContext.AspNetUserID = claims.First(p => p.Type == "sub").Value;
}
}
public UserContext GetUserContext()
{
return _userContext;
}
public bool IsUserAuthenticated()
{
return _context.User != null && _context.User.Identity != null && _context.User.Identity.IsAuthenticated;
}
}
}
HttpContext
在调用Controller的构造函数时不可用。您将不得不重新设计代码,以便稍后在调用流程中获取上下文。这就是 IHttpContextAccessor
的用途。
public interface IHttpContextAccessor {
HttpContext HttpContext { get; }
}
将其注入服务,然后根据需要访问上下文。
public class UserContextService : IUserContextServices {
private readonly IHttpContextAccessor contextAccessor;
private UserContext _userContext;
public UserContextService(IHttpContextAccessor accessor) {
contextAccessor = accessor;
}
private HttpContext Context {
get {
return contextAccessor.HttpContext;
}
}
public UserContext GetUserContext() {
if (_userContext == null && IsUserAuthenticated()) {
var claims = Context?.User?.Claims;
_userContext = new UserContext() {
Email = claims.First(p => p.Type == "email").Value,
AspNetUserID = claims.First(p => p.Type == "sub").Value
};
}
return _userContext;
}
public bool IsUserAuthenticated() {
return Context?.User?.Identity?.IsAuthenticated;
}
}
将服务抽象注入控制器
[Route("api/[controller]")]
[Authorize]
public class UserController : Controller {
private readonly IUserContextServices _userContextServices;
private readonly User loggedUser;
public UserController(IUserContextServices userContextServices) {
_userContextServices = userContextServices;
}
//...
}
IHttpContextAccessor
默认情况下不在服务集合中,因此您需要手动将其添加到 Startup.ConfigureServices
中以便能够注入它:
services.AddHttpContextAccessor();
services.AddTransient<IUserContextServices, UserContextService>();