在控制器外使用 HttpContext

Using HttpContext outside of a controller

public class UserAccount
{
  private readonly IHttpContextAccessor _httpContextAccessor;

  public UserAccount(IHttpContextAccessor httpContextAccessor)
  {
    _httpContextAccessor = httpContextAccessor;
  }

  //Sign in
  public static async Task SignIn(dynamic user)
  {
    var claims = new[]
    {
      new Claim("UserID", user.ID.ToString()),
      new Claim(ClaimTypes.Role, "Baller")
    };

    var principal = new ClaimsPrincipal(
          new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme));

    await _httpContextAccessor.HttpContext.Authentication.SignInAsync("Cookies", principal);
  }
}

我在 SignIn 方法中的 await 语句中收到此错误:非静态字段、方法或 属性 "UserAccount._httpContextAccessor" 需要对象引用

如果我不将该方法声明为静态,错误就会消失,但是如果该方法未声明为静态,我无法从我的控制器访问该方法UserAccount.SignIn。

如果我这样声明变量 _httpContextAccessor

private static IHttpContextAccessor

而不是:

private readonly IHttpContextAccessor

所有错误都消失了,但我再次在 await 语句中遇到空引用异常。 (_httpContextAccessor 未设置为对象的实例)

我认为您打算查看 current HttpContext。为此,您需要将 IHttpContextAccessor 的依赖项添加到您的控制器构造函数,然后在您的操作方法中使用该接口的 HttpContext 属性 来访问当前上下文。

您可能需要注册

services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

在您的 Startup.cs 中,具体取决于您是否已将此服务添加到可能依赖它的其他常见服务中。

I'm getting this error

您不能从静态成员访问实例成员。您可能想继续阅读 static members

The error disappears if I don't declare the method as static

是的,因为实例方法可以访问实例字段。

however from my controllers I can't access the method UserAccount.SignIn if the method ISN'T declared as static.

他们当然可以 - 但他们需要一个 实例:

private UserAccount _userAccount;
ControllerConstructor(IHttpContextAccessor accessor)
{
  _userAccount = new UserAccount(accessor);
}

...
// Inside an action method:
await _userAccount.SignIn(user);

If I declare the variable _httpContextAccessor [as static], all errors go away

是的,因为静态方法可以访问静态字段。

but I get a null reference exception on the await statement again.

因为静态字段从未被初始化。

您这样访问 HttpContext:

@if (Context.User.Identity.IsAuthenticated)
{
    <ul class="nav navbar-nav navbar-right">
        <li>
            <a asp-area="" asp-controller="User" asp-action="Logout">Logout</a>
        </li>
    </ul>
}
else
{
    <ul class="nav navbar-nav navbar-right">
        <li><a asp-area="" asp-controller="User" asp-action="Register">Register</a></li>
        <li><a asp-area="" asp-controller="User" asp-action="Login">Log in</a></li>
    </ul>
}

不需要指令或包。

我的解决方案:

在启动中注册HttpContextAccessor

services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

然后获取当前用户:

using (var scope = host.Services.CreateScope())
{
    var currentContext = scope.GetService<IHttpContextAccessor>();
    return currentContext.HttpContext.User;
}