我对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") })'
应返回/api/v1/programs/43808405-afca-4abb-a92a-519489d62290/versions/latest
但是,我却得到/Programs/GetLatestVersionInfo?telemetryKey=43808405-afca-4abb-a92a-519489d62290
。因此,我的routeprefix和route属性将被忽略。
Swagger正确地发现了我的路线,并且我可以验证对预期路线的请求是否正常运行-只是Url.Action()令人困惑。
有什么问题...?
答案 0 :(得分:0)
尝试以下操作:
命名您的路线:
[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") })
答案 1 :(得分:0)
好吧,看来有些错误。
错误的助手: 我应该使用Url.HttpRouteUrl从剃刀视图生成API链接(Url.Link用于从API控制器内部生成链接)
与aspnet-api-versioning 库冲突
由于某种原因(也许是错误?),我在控制器上使用的前缀(apiVersion
变量)破坏了URL帮助器机制。
目前,我已经放弃了aspnet-api-versioning库,但是在他们的github仓库上创建了一个问题,以防万一它是一个错误。
由于我真的很讨厌创建和维护魔术字符串的想法,因此我采取了以下方法-每个控制器都有一个公共静态类,其中包含路由名称的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 */})
比魔术弦好。我还为控制器添加了一堆单元测试,可以验证每个路由的唯一性和正确性,以及路由类仅包含其所包含操作的路由。