Asp.Net核心中间件服务依赖于当前用户

时间:2016-02-12 15:07:22

标签: asp.net-core

我想更改请求范围的服务或在自定义中间件层中设置一个。

具体来说,我希望能够在Startup.cs中执行类似下面的设计示例:

public void ConfigureServices(IServiceCollection service)
{
    service.AddScoped<IMyUserDependentService>((provider) => {
        return new MyService());
    });
}

public void Configure(...) {

    //other config removed

    app.Use(async (context, next) => {

        var myService = context.ApplicationServices.GetService<IMyUserDependentService>();


        myService.SetUser(context.User.Identity.Name);//Name is Fred

        next.Invoke();
    });
}

然后在控制器中执行以下操作:

public class HomeController: Controller
{
    public HomeController(IMyUserDependentService myService)
    {
        //myService.UserName should equal Fred
    }
}

问题是,这不起作用。 myService.UserName在控制器中不是Fred,它是null。我认为IOC容器正在控制器中创建一个新实例,而不是使用中间件中的一个。

如果我将服务范围更改为Transient,Fred会被记住,但这并不会有帮助,因为该服务取决于当前用户是谁。

总结一下,我需要的是创建/或编辑需要当前用户(或其他当前请求变量)的服务,但我无法解决这个问题。

提前致谢!

2 个答案:

答案 0 :(得分:4)

您是否尝试过使用context.RequestServices

答案 1 :(得分:0)

我遇到了类似的问题,出现了类似的错误 InvalidOperationException: Cannot resolve scoped service 'IScopedService' from root provider.,引发的异常情况没有得到很好的记录。

这是我解决的方法:

[Startup.cs]

services.AddScoped<IAnyScopedService, AnyScopedService>();
services.AddSingleton<ISomeOtherSingletonService, SomeOtherSingletonService>();

[MyMiddleware.cs]

public sealed class MyMiddleware
{
    private readonly RequestDelegate _next;
    private readonly ISomeOtherSingletonService _Svc;

    public MyMiddleware(
              RequestDelegate next,
              ISomeOtherSingletonService svc)
    {
        _next = next;
        _Svc = svc;
    }

    public async Task Invoke(HttpContext context,
              IAnyScopedService scopedService)
    {
        // Some work with scoped service
    }
}

实际上,中间件仅被实例化一次,但是被调用了很多次。 因此,构造函数采用单例实例,在该实例中invoke方法可以获取作用域内注入的参数。

有关Mark Vincze post的详细信息