控制器中的范围服务与中间件中调用的服务不同

时间:2016-06-07 20:57:55

标签: c# dependency-injection asp.net-core asp.net-core-mvc

我有一个自定义身份验证Middelware,它使用我在构造函数中注入的自定义服务。

MyAuthenticationHandler我正在调用一个设置属性值的MyService方法。

_myService.SetCompany(company);

公司已加载到身份验证处理程序中,并且不为null。但是,当我尝试从控制器访问该值时,我发现MyService已重新初始化。

这是在Startup.cs中设置的方式

services.AddScoped<IMyService, MyFactory>();

2 个答案:

答案 0 :(得分:4)

中间件仅在您注册时初始化一次。您需要在Invoke方法中解决您的依赖关系。

public class MyMiddleware
{
    private readonly RequestDelegate _next;
    private readonly ILogger _logger;

    public MyMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task Invoke(HttpContext context)
    {
        var service = context.RequestServices.GetService<IMyService>();
        service.SetCompany("My Company");

        await _next.Invoke(context);
    }
}

现在,每个请求都可以正确解析服务,而不是每个应用程序的生命周期。

修改

即。为了在授权middelware之后调用您的中间件,您可以在Configure(IAppBuilder app)方法中执行以下操作:

app.UseCookieAuthentication(options => { ... });
app.UseJwtBearerAuthentication(options => { ... });
app.UseMiddleware<MyMiddleware>(options => { ... });

然后在请求中,首先调用cookie中间件。如果它可以处理该方案并且它失败,则不会执行以下中间件。如果它不能处理该方案,则将调用下一个(jwt bearer)。如果通过,将调用下一个中间件(MyMiddleware)。

换句话说,当您调用MyMiddleware.Invoke()方法时,用户已经过身份验证。

答案 1 :(得分:0)

您可以直接在Invoke签名中注入服务。

来自官方文档here

  

如果必须在中间件和其他类型之间共享作用域服务,请将这些服务添加到Invoke方法的签名中。 Invoke方法可以接受依赖注入填充的其他参数。

所以在你的情况下:

public async Task Invoke(HttpContext context, IMyService service)
{
    service.SetCompany("My Company");

    await _next.Invoke(context);
}

会奏效。