我正在尝试根据发送到服务的HTTP标头将请求路由到不同的控制器。
在我的Configure
方法中,我有
app.MapWhen(ctx => !string.IsNullOrWhiteSpace(ctx.Request.Headers["Magic"]), DoStuff);
我的问题是我不知道如何指定控制器,甚至修改路径
private static void DoStuff(IApplicationBuilder app)
{
/// ?!? \\\
}
理想情况下,我希望如果发送标头Magic: Missile
,则将路由重写为/Missile
答案 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)
{
}