ASP中基于报头的路由.净的核心



我正在尝试根据发送到服务的HTTP头将请求路由到不同的控制器。

Configure方法中,我有

app.MapWhen(ctx => !string.IsNullOrWhiteSpace(ctx.Request.Headers["Magic"]), DoStuff);

我的问题是我不知道如何指定控制器,甚至修改路由

 private static void DoStuff(IApplicationBuilder app)
 {
    /// ?!? \
 }

理想情况下,我想,如果头Magic: Missile被发送,重写路由为/Missile

虽然编写自定义中间件当然是一个不错的选择,但另一个选择是创建一个操作约束(通过实现IActionContraint接口)。这将允许你用指定头的属性来修饰你的方法/value,该值必须在请求中提供,以便调用给定方法。

我发现这在使用WebHooks时特别有用,因为外部系统对所有hook使用单个URL,并使用标题来区分不同的操作类型。

这个属性的简单实现如下:

public class HttpHeaderAttribute : Attribute, IActionConstraint
{
    public string Header { get; set; }
    public string Value { get; set; }
    public HttpHeaderAttribute (string header, string value)
    {
        Header = header;
        Value = value;
    }
    public bool Accept(ActionConstraintContext context)
    {
        if (context.RouteContext.HttpContext.Request.Headers.TryGetValue(Header, out var value))
        {
            return value[0] == Value;
        }
        return false;
    }
    public int Order => 0;
}

下面是如何使用它的示例:

    [HttpPost, Route("webhook"), HttpHeader("X-Drchrono-Event", "PATIENT_CREATE")]
    public IActionResult DrChronoPatientCreate(WebHookData data)
    {
    }
    [HttpPost, Route("webhook"), HttpHeader("X-Drchrono-Event", "PATIENT_MODIFY")]
    public IActionResult DrChronoPatientModify(WebHookData data)
    {
    }

在触及mvc层之前,我最终编写了一个自定义中间件来重写uri。工作很好!

public Task Invoke(HttpContext context)
{
    const string apiPath = "/api";
    var magic context.Request.Headers["Magic"];
    if (string.IsNullOrWhiteSpace(magic))
    {
        return _next.Invoke(context);
    }
    var path = context.Request.Path.ToUriComponent();
    if (!path.StartsWith(apiPath))
    {
        return _next.Invoke(context);
    }
    path = string.Concat(path.Skip(apiPath.Length));
    path = $"{apiPath}/{magic}{path}";
    context.Request.Path = path;
    return _next.Invoke(context);
}

最新更新