当 ASP.NET Core 遇到命名不明确的路由时,它会变得惰性。也就是说,应用程序将运行而不会抛出异常,但是它将无法处理任何 Controller 上的任何请求。调用客户端收到 500 个响应。
我将展示我是如何陷入这种困境的,并且我希望得到有关如何解决它的建议。
我有一个看起来像这样的 Controller :
[Route("api/Subscribers/{id}/[controller]")]
[Route("api/Organizations/{id}/[controller]")]
public class AddressesController : Controller
{
[HttpGet("{aid}", Name = "PostalLink")]
public async Task<IActionResult> GetAddress(Guid id, Guid aid)
{
//...implementation is irrelevant for this question.
}
[HttpPost]
[SwaggerResponseRemoveDefaults]
[SwaggerResponse(HttpStatusCode.Created, Type = typeof(PostalRecord))]
public async Task<IActionResult> CreateAddress(Guid id, [FromBody] PostalAddress address)
{
address.ID = Guid.NewGuid();
await createAddress.Handle(address);
return CreatedAtRoute("PostalLink", new { id = id, aid = address.ID });
}
为什么 Controller 上有两个路由前缀?因为它符合我的微服务(和 Swagger 文档)策略。然而,在此示例中,ASP.NET Core 不知道如何解析路由名称“PostalLink”,因为它隐式绑定(bind)到两个前缀:
[Route("api/Subscribers/{id}/[controller]")]
[Route("api/Organizations/{id}/[controller]")]
我可以简单地通过更改 HttpGet
来解决这个问题,而不是这样:
[HttpGet("{aid}", Name = "PostalLink")]
我有这个:
[HttpGet("{aid}")] //the route is no longer "named"
不幸的是,删除路由名称对我来说不是一个真正的选择。
解决此问题的规定方法是什么?
以下是我正在考虑的一些选项。
可能性 #1
理论上,ASP.NET 可以简单地自行“解决”。例如,如果当前请求解析为包含单词“Subscribers”的路由,则“PostalLink”名称应引用该路由。这样看来,也许我的代码暴露了 ASP.NET Core 中的错误、缺陷或疏忽。
可能性#2
我可以像这样将两个前缀路由折叠成一个路由:
[Route("api/{parent}/{id}/[controller]")]
这行得通,但它破坏了我的 REST 文档策略。我正在使用 Swashbuckle 发布端点元数据。我希望我的 API 的用户明确看到我的“地址”API 服务于“订阅者”或“组织”。当我有两个显式路由前缀时,Swagger 文档可以正常工作(并且我可以正确验证客户端使用的 URI)。
可能性 #3
我可以像这样简单地覆盖两个前缀:
[HttpGet("~/api/Subscribers/{id}/Addresses/{aid}", Name = "SubscriberLink")]
[HttpGet("~/api/Organizations/{id}/Addresses/{aid}", Name = "OrganizationLink")]
public async Task<IActionResult> GetAddress(Guid id, Guid aid)
{
//...implementation is irrelevant for this question.
}
现在我的文档和路由验证有效,但我的实现被迫检查使用哪条路由到达端点。这是非常可行的,但非常烦人。
可能性 #4
也许没有基于属性的路由,有一种更具表现力的方法来处理这个问题?如果是,请分享!
详情
我的project.json配置如下:
"frameworks": {
"dnx46": { }
},
我使用的是 DNX SDK 版本 1.0.0-rc1-update1。另外,我发布了一个 related SO question对于那些想要更多了解我正在尝试做的事情的人。
最佳答案
如果所有操作的路由名称都相同,为什么不直接在 Controller 上指定它们?
[Route("api/Subscribers/{id}/[controller]", Name = "SubscriberLink")]
[Route("api/Organizations/{id}/[controller]", Name = "OrganizationLink")]
public class AddressesController : Controller
{
[HttpGet("{aid}")]
public async Task<IActionResult> GetAddress(Guid id, Guid aid)
{
//...implementation is irrelevant for this question.
}
}
关于c# - ASP.NET Core (MVC 6) 中的路由消歧,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36522617/