使用中间件注入路由数据

Inject route data using middleware

我正在构建一个非常简单的 rest api。我在特定控制器下的所有端点都需要一个 QueryContext 类型的对象。此对象是 HttpRequest 的 "simplified" 版本。

目前,我使用工厂接受 HttpRequest 并返回 QueryContext 类型的对象。

public interface IQueryContextFactory
{
    QueryContext Create(string query, HttpRequest request);
}

internal class HttpRequestQueryContextFactory : IQueryContextFactory
{
    public QueryContext Create(string query, HttpRequest request)
    {
        if (string.IsNullOrEmpty(query))
            throw new ArgumentNullException(nameof(query));
        if (request == null)
            throw new ArgumentNullException(nameof(request));

        return new QueryContext
        {
            Method = request.Method,
            QueryString = string.Concat(query, request.QueryString),
            Parameters = request.Query.ToDictionary(x => x.Key, x => x.Value.ToString().Replace("\"", string.Empty)),
            Headers = request.Headers.ToDictionary(x => x.Key, x => x.Value.ToString())
        };
    }
}

然后我从我的端点调用这个工厂

    [HttpGet]
    public IActionResult Process(string query)
    {
        (...)
        var ctx = _contextFactory.Create(query, Request);
    }

是否推荐使用中间件将QueryContext 添加到路由数据中?这个我能把它作为参数吗?

您可以在 API 控制器中注入一个 IQueryContextFactory。

这是一个例子:

[Route("api/my")]
public class MyController : Controller {

    private readonly IQueryContextFactory QueryContextFactory;

    public MyController(IQueryContextFactory queryContextFactory) {
      if (queryContextFactory == null)
        throw new ArgumentNullException(nameof(queryContextFactory));
      QueryContextFactory = queryContextFactory;
    }

    [HttpGet]
    public IActionResult Get(string query) {
      var ctx = QueryContextFactory.Create(query, Request);
      return Ok();
    }
}

然后,您在 Startup.cs 中配置注入,如下所示:

public void ConfigureServices(IServiceCollection services) {
  //...
  services.AddSingleton<IQueryContextFactory, HttpRequestQueryContextFactory>();
  //...
}

您可以找到有关注入的更多信息here

如您所示,简化的 QueryContext class 中的所有数据也在 HttpContext 中。您可以做一些不同的事情,而不是将另一个对象注入您的控制器。

  1. 初始化 QueryContext 属性 或输入控制器的构造函数。这样它就可以用于所有控制器方法而无需重复代码。

  2. 而是添加一个新的 class extend HttpContext class 以及一些可以满足您需要的扩展方法。