【问题标题】:initialize objects in ASP.custom middleware and inject them在 ASP.custom 中间件中初始化对象并注入它们
【发布时间】:2018-08-12 08:15:45
【问题描述】:

我有一个 ASP.NET Core Web API,它读取请求标头中的身份验证令牌并解码其中的值。

我已经编写了自定义中间件来解码令牌。我还创建了一个 UserContext 对象来保存从令牌解码的值,并将解码后的值设置到 UserContext 对象中。

我现在希望能够将 UserContext 对象(在自定义中间件中创建)注入到我的控制器中,但我不知道该怎么做。

请帮忙。

【问题讨论】:

  • 显示一些代码。没有它就无法提供太多帮助。

标签: asp.net-web-api asp.net-core .net-core


【解决方案1】:

您可以使用HttpContext.Items

在您的中间件中,您当然可以访问HttpContext

您可以将您的用户上下文存储在项目字典中,该字典是瞬态的,并且范围仅限于一个 http 请求的生命周期。下面是一个示例中间件,其中 'context' 是 Http 上下文对象。您将在中间件中拥有此对象。

app.Use(async (context, next) =>
{
 context.Items.Add("UserContext", new UserContext());
 await next.Invoke();
});

然后,您可以通过注入 IHttpContextAccessor 对象来访问控制器中的 HttpContext

 public class ApiController : Controller
 {
    public readonly IHttpContextAccessor _context;
    public ApiController(IHttpContextAccessor context)
    {
        _context = context;
    }

    public IActionResult Get()
    {
        // Get the http context
        UserContext userContext = (UserContext) _context.HttpContext.Items["UserContext"];
        return Ok();
    }
  }

IHttpContextAccessor,你可以得到HttpContext对象,你可以从中得到Items字典。

当然,做一些检查以查看密钥“UserContext”是否存在,但我认为这对你有用

编辑

因为您希望将其传递给其他存储库/服务。
而不是将HttpContextAccessor 传递给所有人,您可以这样做。创建一个服务,封装UserContext 对象的创建。

它可能看起来像这样。

public interface IRepositry { }

    public class Repositry : IRepositry
    {
        private IUserContextService _userContextService;
        public Repositry(IUserContextService userContextService)
        {
            _userContextService = userContextService;
        }
    }

public class UserContext
{

}

public interface IUserContextService
{
    UserContext GetUser();
}

public class UserContextService : IUserContextService
{
    private readonly IHttpContextAccessor _context;

    public UserContextService(IHttpContextAccessor context)
    {
        _context = context;
    }
    public UserContext GetUser()
    {
        var token = _context.HttpContext.Request.Headers["UserToken"];
        // do something with the token to create the UserContext;
        return new UserContext();
    }
}

创建一个从HttpContext 读取的UserContextService。将UserContextService 设为单例,但是当您获取用户时,始终返回一个新的UserContext,这是因为您当然处于多线程环境中,并且您永远不想保留此对象,因为您最终可能会阅读其他人的UserContext,所以总是返回新的。在启动类的 ConfigureServices 方法中注册此服务。

public void ConfigureServices(IServiceCollection services)
{
    services.AddSingleton<IUserContextService, UserContextService>();
    services.AddSingleton<IRepositry, Repositry>(serviceCollection => new Repositry(serviceCollection.GetService<IUserContextService>()));

}

然后您可以将您的存储库注入到您的 API 控制器中,例如

public class ApiController : Controller
{
    public readonly IRepositry _repositry;
    public ApiController(IRepositrycontext repositry)
    {
        _repositry= repositry;
    }

    public IActionResult Get()
    {
        // Get the http context

        return Ok();
    }
 } 

【讨论】:

  • 谢谢。如果我想将 UserContext 传播到服务/存储库层,我该如何使用这种方法呢?我应该改用过滤器吗?
  • 我已经更新了我的答案。这是您可以做到的一种方式。希望这会有所帮助:)
  • 嗨,奥马尔,非常感谢!我将对此进行测试并在此处更新。感谢您的帮助。
  • 这行得通!谢谢奥马尔。我接受这个答案。
  • 为什么不在 DI 中注册为 Scoped 的简单类?并在此类的构造函数中注入 IHttpContextAccessor 并设置对象属性。 Scoped 是每个请求一个,对吧?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-02
  • 2018-02-10
  • 1970-01-01
  • 2014-12-27
  • 2012-08-30
  • 1970-01-01
相关资源
最近更新 更多