Url.Action 为带有 Route 属性的 web api 操作返回不正确的 URL
Url.Action returning incorrect URL for webapi action with Route attrubute
我对 Url.Action();
的行为有疑问
我有一个 webapi,其中所有控制器都需要显式路由前缀属性,所有操作都需要路由属性。
我在 WebApiConfig.cs
中注册了我的路线
var constraintResolver = new DefaultInlineConstraintResolver()
{
ConstraintMap =
{
["apiVersion"] = typeof( ApiVersionRouteConstraint )
}
};
config.MapHttpAttributeRoutes(constraintResolver);
我目前已经注释掉了下面这行,但是(因为)它并没有改变不正确的行为:
//config.Routes.MapHttpRoute(name: "DefaultApi",
//routeTemplate: "api/v{version:apiVersion}/{controller}/{action}/{id}", defaults: new {id = RouteParameter.Optional});
我的控制器如下所示:
[RoutePrefix("api/v{version:apiVersion}/programs")]
public class ProgramsController : ApiController
{
[HttpGet, Route("{telemetryKey}/versions/latest")]
public async Task<LatestVersionResponse> GetLatestVersionInfo(Guid telemetryKey)
{
// serious business logic
}
}
我希望 '@Url.Action("GetLatestVersionInfo", "Programs", new { telemetryKey = Guid.Parse("43808405-afca-4abb-a92a-519489d62290") })'
应该return/api/v1/programs/43808405-afca-4abb-a92a-519489d62290/versions/latest
然而,我得到的是 /Programs/GetLatestVersionInfo?telemetryKey=43808405-afca-4abb-a92a-519489d62290
。所以,我的路由前缀和路由属性被忽略了。
Swagger 正确地发现了我的路线,我可以验证对预期路线的请求是否正常工作 - 只有 Url.Action() 令人困惑。
有什么问题...?
尝试以下操作:
为您的路线命名:
[HttpGet, Route("{telemetryKey}/versions/latest", Name="LatestVersionInfoRoute")]
public async Task<LatestVersionResponse> GetLatestVersionInfo(Guid telemetryKey)
{
// serious business logic
}
使用Url.Link方法:
@Url.Link("LatestVersionInfoRoute", new { telemetryKey = Guid.Parse("43808405-afca-4abb-a92a-519489d62290") })
嗯,似乎有一些地方不对。
错误的帮手:
我应该使用 Url.HttpRouteUrl 从剃刀视图中生成 API link(Url.Link 用于从 API 控制器中生成 link)
与 aspnet-api-versioning 库冲突
出于某种原因(也许是一个错误?)我在控制器上的前缀(apiVersion
变量)破坏了 URL 辅助机制。
现在,我已经放弃了 aspnet-api-versioning 库,但在他们的 github 回购协议上创建了一个问题,以防它是一个错误。
因为我真的很讨厌创建和维护魔法字符串的想法,所以我采用了以下方法 - 每个控制器都有一个 public static class,其中包含路由名称的 const 值:
[RoutePrefix("api/v1/developers")]
public class DevelopersController : ApiController
{
[HttpGet, Route("{developerId}/programs", Name = Routes.GetPrograms)]
public async Task<IEnumerable<Program>> GetPrograms(Guid developerId){}
public static class Routes
{
public const string GetPrograms = nameof(DevelopersController) +"."+ nameof(DevelopersController.GetPrograms);
}
}
现在可以通过剃须刀控制器以简单且相对安全的方式使用它:
@Url.HttpRouteUrl(DevelopersController.Routes.GetPrograms, new { developerId = /* uniquest of guids */})
比魔术弦好一点。我还为控制器添加了一堆单元测试,我在其中验证每条路线都是唯一且正确的,并且路线 class 仅包含其包含的操作的路线。
我对 Url.Action();
的行为有疑问我有一个 webapi,其中所有控制器都需要显式路由前缀属性,所有操作都需要路由属性。
我在 WebApiConfig.cs
中注册了我的路线 var constraintResolver = new DefaultInlineConstraintResolver()
{
ConstraintMap =
{
["apiVersion"] = typeof( ApiVersionRouteConstraint )
}
};
config.MapHttpAttributeRoutes(constraintResolver);
我目前已经注释掉了下面这行,但是(因为)它并没有改变不正确的行为:
//config.Routes.MapHttpRoute(name: "DefaultApi",
//routeTemplate: "api/v{version:apiVersion}/{controller}/{action}/{id}", defaults: new {id = RouteParameter.Optional});
我的控制器如下所示:
[RoutePrefix("api/v{version:apiVersion}/programs")]
public class ProgramsController : ApiController
{
[HttpGet, Route("{telemetryKey}/versions/latest")]
public async Task<LatestVersionResponse> GetLatestVersionInfo(Guid telemetryKey)
{
// serious business logic
}
}
我希望 '@Url.Action("GetLatestVersionInfo", "Programs", new { telemetryKey = Guid.Parse("43808405-afca-4abb-a92a-519489d62290") })'
应该return/api/v1/programs/43808405-afca-4abb-a92a-519489d62290/versions/latest
然而,我得到的是 /Programs/GetLatestVersionInfo?telemetryKey=43808405-afca-4abb-a92a-519489d62290
。所以,我的路由前缀和路由属性被忽略了。
Swagger 正确地发现了我的路线,我可以验证对预期路线的请求是否正常工作 - 只有 Url.Action() 令人困惑。
有什么问题...?
尝试以下操作:
为您的路线命名:
[HttpGet, Route("{telemetryKey}/versions/latest", Name="LatestVersionInfoRoute")]
public async Task<LatestVersionResponse> GetLatestVersionInfo(Guid telemetryKey)
{
// serious business logic
}
使用Url.Link方法:
@Url.Link("LatestVersionInfoRoute", new { telemetryKey = Guid.Parse("43808405-afca-4abb-a92a-519489d62290") })
嗯,似乎有一些地方不对。
错误的帮手: 我应该使用 Url.HttpRouteUrl 从剃刀视图中生成 API link(Url.Link 用于从 API 控制器中生成 link)
与 aspnet-api-versioning 库冲突
出于某种原因(也许是一个错误?)我在控制器上的前缀(apiVersion
变量)破坏了 URL 辅助机制。
现在,我已经放弃了 aspnet-api-versioning 库,但在他们的 github 回购协议上创建了一个问题,以防它是一个错误。
因为我真的很讨厌创建和维护魔法字符串的想法,所以我采用了以下方法 - 每个控制器都有一个 public static class,其中包含路由名称的 const 值:
[RoutePrefix("api/v1/developers")]
public class DevelopersController : ApiController
{
[HttpGet, Route("{developerId}/programs", Name = Routes.GetPrograms)]
public async Task<IEnumerable<Program>> GetPrograms(Guid developerId){}
public static class Routes
{
public const string GetPrograms = nameof(DevelopersController) +"."+ nameof(DevelopersController.GetPrograms);
}
}
现在可以通过剃须刀控制器以简单且相对安全的方式使用它:
@Url.HttpRouteUrl(DevelopersController.Routes.GetPrograms, new { developerId = /* uniquest of guids */})
比魔术弦好一点。我还为控制器添加了一堆单元测试,我在其中验证每条路线都是唯一且正确的,并且路线 class 仅包含其包含的操作的路线。