ASP.NET Core中基于头的路由

时间:2016-09-03 00:15:56

标签: routing asp.net-core

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

在我的Configure方法中,我有

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

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

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

理想情况下,我希望如果发送标头Magic: Missile,则将路由重写为/Missile

2 个答案:

答案 0 :(得分:6)

我最终编写了一个自定义中间件来重写uri,然后才进入mvc层。很好用!

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);
}

答案 1 :(得分:2)

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

我发现这在使用WebHooks时特别有用,在WebHooks中,外部系统对所有挂钩使用单个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)
    {

    }