【发布时间】:2020-07-17 11:32:59
【问题描述】:
我正在将旧版 .NET 应用程序移植到 .NET Core Web API。
旧版应用程序公开了一个我必须 1:1 移植的 API。
我的以下请求路径运行良好:
GET https://localhost:5001/MySuperController/user@example.com
GET https://localhost:5001/MySuperController/?username=user@example.com
POST https://localhost:5001/MySuperController/?username=user@example.com
swagger: GET https://localhost:5001/doc
但是我在路由以下两条路径到达根 URL 时遇到问题:
GET https://localhost:5001/?username=user@example.com
POST https://localhost:5001/?username=user@example.com
这是我的控制器和招摇注册:
app.UseEndpoints(endpoints => { endpoints.MapControllers(); });
if (EnvironmentConfiguration.EnvironmentType == SystemConstants.DevEnvironment)
{
app.UseSwagger(s =>
{
s.RouteTemplate = "doc/{{documentName}}/docs.json";
});
app.UseSwaggerUI(c =>
{
c.RoutePrefix = "doc";
c.SwaggerEndpoint($"../doc/v1/docs.json", "API reference");
});
}
这是控制器的简化实现:
[Route("[controller]")]
[ApiController]
public class MySuperController
{
// GET https://localhost:5001/MySuperController/user@example.com
[HttpGet("{emailaddress}")]
public IActionResult Get(...) {...}
// GET https://localhost:5001/MySuperController/?username=user@example.com
[HttpGet()]
public IActionResult Get(...) {...}
// POST https://localhost:5001/MySuperController/?username=user@example.com
[HttpPost()]
public async Task<IActionResult> Post(...) {...}
}
为了支持以下两个查询,我添加了[Route("")] 前缀。但现在我将https://localhost:5001/doc 匹配到第一个控制器操作中,{emailaddress} 被"doc" 填充。
GET https://localhost:5001/?username=user@example.com
POST https://localhost:5001/?username=user@example.com
[Route("[controller]")]
[Route("")]
[ApiController]
public class MySuperController
{
// also matches https://localhost:5001/doc now :(
// GET https://localhost:5001/MySuperController/user@example.com
[HttpGet("{emailaddress}")]
public IActionResult Get(...) {...}
// GET https://localhost:5001/?username=user@example.com
// GET https://localhost:5001/MySuperController/?username=user@example.com
[HttpGet()]
public IActionResult Get(...) {...}
// POST https://localhost:5001/?username=user@example.com
// POST https://localhost:5001/MySuperController/?username=user@example.com
[HttpPost()]
public async Task<IActionResult> Post(...) {...}
}
使用 Web API 正确路由这些查询的最惯用方法是什么?如果可能的话,我不希望将控制器拆分为多个控制器。
【问题讨论】:
-
如果你把
[Route("/my/path-to-something")]放在动作方法上,你可以明确定义它们的所有URL。 -
我在移植应用程序时也遇到了复杂的路由问题。然后我使用了
DynamicRouteValueTransformer。见这里:github.com/dotnet/AspNetCore.Docs/issues/12997 你可以在app.useEndpoings(endpoints => endpoints.MapDynamicControllerRoute<MyTransforer>(...)注册它。在这个转换器中,您拥有带有所有查询参数的 httpContext、asp.net 将使用的 RouteValueDictionary,您可以使用任何逻辑来更改该路由。 -
@MartinCostello 感谢您为我指明了正确的方向!
-
@gofal3 感谢您的想法!幸运的是,在没有您链接的真正大工具的情况下,我设法解决了问题:D
标签: c# asp.net asp.net-core asp.net-web-api