问题 ASP.NET核心中间件将参数传递给控制器


我正在使用ASP.NET Core Web API,我有多个独立的web api项目。在执行任何控制器的操作之前,我必须检查登录用户是否已经模仿其他用户(我可以从DB获取)并且可以将模拟的用户ID传递给操作。

由于这是一段可以重复使用的代码,我想我可以使用中间件:

  • 我可以从请求标头获取初始用户登录
  • 获取被授权的用户ID(如果有)
  • 在请求管道中注入该ID,以使其可用于被调用的api
public class GetImpersonatorMiddleware
{
    private readonly RequestDelegate _next;
    private IImpersonatorRepo _repo { get; set; }

    public GetImpersonatorMiddleware(RequestDelegate next, IImpersonatorRepo imperRepo)
    {
        _next = next;
        _repo = imperRepo;
    }
    public async Task Invoke(HttpContext context)
    {
        //get user id from identity Token
        var userId = 1;

        int impersonatedUserID = _repo.GetImpesonator(userId);

        //how to pass the impersonatedUserID so it can be picked up from controllers
        if (impersonatedUserID > 0 )
            context.Request.Headers.Add("impers_id", impersonatedUserID.ToString());

        await _next.Invoke(context);
    }
}

我找到了这个 ,但这没有解决我正在寻找的问题。

如何传递参数并使其在请求管道中可用?是否可以将其传递到标题中或者有更优雅的方式来执行此操作?


5375
2018-03-14 14:05


起源

您应该更改请求上下文,而不是管道本身。 - Lex Li
@LexLi,您能否通过一个例子详细说明,您的意思是向请求本身添加一些信息并从控制器获取吗?如果那就是你的意思,那我正在考虑这个问题,但是再次查询,身体,不会影响被调用的行为? - Coding


答案:


您可以使用HttpContext.Items在管道内传递任意值:

context.Items["some"] = "value";

8
2018-03-14 15:12



也可以看看: 使用HttpContext.Items - poke
我正在使用Session。 context.Session.SetInt32("user-id", 12345); 哪种方法最好?为什么? - Muhammad Saqib
可以启用或不启用会话,并且它们需要cookie。 - Ricardo Peres


更好的解决方案是使用范围服务。看看这个: https://docs.microsoft.com/en-us/aspnet/core/fundamentals/middleware/?tabs=aspnetcore2x#per-request-dependencies

您的代码应如下所示:

public class MyMiddleware
{
    private readonly RequestDelegate _next;

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

    public async Task Invoke(HttpContext httpContext, IImpersonatorRepo imperRepo)
    {
        imperRepo.MyProperty = 1000;
        await _next(httpContext);
    }
}

然后将您的ImpersonatorRepo注册为:

services.AddScoped<IImpersonatorRepo, ImpersonatorRepo>()

5
2018-02-05 14:23