我试图在我的网关上创建一个控制器,除了代理请求到另一个API之外几乎什么都不做。(它做了一些其他非常基本的准备工作,但这有点超出了本文的范围,所以我把它省略了)。这以前是由大约20个控制器处理的,它们都做同样的事情,所以我试图简化事情。
[Route("api/reporting/route1")]
[Route("api/reporting/route2")]
public class TestController : Controller
{
[HttpPost("{clientId:int")]
public async Task<ActionResult<MemoryStream>> GetReport(int clientId, [FromBody] object requestBody)
{
var report = await ReportingClient.DownloadReport(/*HERE*/, requestBody);
return File(report, "application/pdf");
}
}
目的地完全由到达该控制器的路由决定。
。route1
可以生成api/reporting/test/1
,route2
可以生成api/test/2
。
已经存在的东西不像我想的那样一致,但是要使它们都一致已经超出了我的范围。
因此,我希望能够用将Route
与任意Target
字符串相结合的属性来装饰我的控制器。
像这样:
[ProxyRoute("api/reporting/route1", "api/reporting/test/1")]
[ProxyRoute("api/reporting/route2", "api/test/2")]
public class TestController : Controller
{
[HttpPost("{clientId:int")]
public async Task<ActionResult<MemoryStream>> GetReport(int clientId, [FromBody] object requestBody)
{
var report = await ReportingClient.DownloadReport(Target, requestBody);
return File(report, "application/pdf");
}
}
当然,我可以在我的类中包含一个静态只读字典来实现这一点,但我觉得那样更麻烦,所以如果可以的话,我想用一个属性来实现。
我该如何做到这一点?
所以我实际上解决了这个…我想我把它想得太复杂了。它所需要的是我从RouteAttribute
本身继承,然后添加我的额外字符串作为公共属性:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = false)]
protected class ReportingProxyRouteAttribute : RouteAttribute
{
public string Destination { get; }
public ReportingProxyRouteAttribute(string template, string destination) : base(template)
{
Destination = destination;
}
}
我可以自己得到额外的字符串:
private ReportingProxyRouteAttribute GetRouteForRequest()
{
var possibleRoutes = Attribute.GetCustomAttributes(GetType(), typeof(ReportingProxyRouteAttribute)).Cast<ReportingProxyRouteAttribute>();
return possibleRoutes.First(r => Request.Path.ToString().ToLowerInvariant().Contains(r.Template.ToLowerInvariant()));
}