带有 IHttpControllerSelector 的 AttributeRouting - Api 版本控制
AttributeRouting with IHttpControllerSelector - Api Versioning
我正在尝试在 asp.net webapi.
上使用 CustomHttpControlSelector 和 AttributeRouting 实现 api 版本控制
我想做的是通过名称空间区分控制器的版本。
如果向 /api/v2/foo/bar 提出请求
我希望它匹配
namespace Web.Controllers.Api.v2
{
[RoutePrefix("foo")]
public class LongerThanFooController : ApiController
{
[HttpGet]
[Route("bar")]
public string BarFunction()
{
return "foobar";
}
}
}
但是正如我所见,当我不在 RoutePrefix (/api/v2/foo) 上使用完整 url 时,属性路由不会启动,当我调用
时我得到 null
request.GetRouteData().GetSubRoutes();
在我的 CustomHttpControlSelector 上。我不想在每个控制器上重复 /api/v2。
如果我决定删除 attributeRouting 并使用像
这样的手动路由
config.Routes.MapHttpRoute(
name: "DefaultVersionedApi",
routeTemplate: "api/v{version}/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional, version = Config.LatestVersion }
);
我失去了命名我的控制器和功能的所有灵活性。
有没有办法摆脱这种困境?
注意:对于 CustomHttpControlSelector,我在 http://aspnet.codeplex.com/SourceControl/changeset/view/dd207952fa86#Samples/WebApi/NamespaceControllerSelector/NamespaceHttpControllerSelector.cs
上修改了代码
我意识到这是一个有点老的问题了,但它可以用 ASP.NET API Versioning package for ASP.NET Web API 来回答。在最新的 3.0 版本中,您可以通过更新配置来实现您的场景:
var constraintResolver = new DefaultInlineConstraintResolver()
{
ConstraintMap =
{
["apiVersion"] = typeof( ApiVersionRouteConstraint )
}
};
configuration.AddApiVersioning(
options =>
{
options.Conventions.Add( new VersionByNamespaceConvention() );
options.AssumeDefaultVersionWhenUnspecified = true;
options.ApiVersionSelector = new CurrentImplementationApiVersionSelector( options );
} );
configuration.MapHttpAttributeRoutes( constraintResolver );
您还应该删除基于约定的路线。如果您使用属性路由,则不需要这些。
您的控制器设置只需更改为:
namespace Web.Controllers.Api.v2
{
[RoutePrefix("api")]
public class LongerThanFooController : ApiController
{
[HttpGet]
[Route("foo/bar")]
[Route("v{version:apiVersion}/foo/bar")]
public string BarFunction()
{
return "foobar";
}
}
}
您需要两个路由定义的原因是您不能在路由模板中间有默认值。默认值只能在最后使用。这也意味着您需要不允许指定任何 API 版本,并指示确定应选择哪个 API 版本的方法是使用当前实现(例如 latest).我个人不喜欢这种方法,因为我认为事情对客户来说应该是可预测的,但这会达到你想要的结果。
我正在尝试在 asp.net webapi.
上使用 CustomHttpControlSelector 和 AttributeRouting 实现 api 版本控制我想做的是通过名称空间区分控制器的版本。
如果向 /api/v2/foo/bar 提出请求 我希望它匹配
namespace Web.Controllers.Api.v2
{
[RoutePrefix("foo")]
public class LongerThanFooController : ApiController
{
[HttpGet]
[Route("bar")]
public string BarFunction()
{
return "foobar";
}
}
}
但是正如我所见,当我不在 RoutePrefix (/api/v2/foo) 上使用完整 url 时,属性路由不会启动,当我调用
时我得到 null request.GetRouteData().GetSubRoutes();
在我的 CustomHttpControlSelector 上。我不想在每个控制器上重复 /api/v2。
如果我决定删除 attributeRouting 并使用像
这样的手动路由 config.Routes.MapHttpRoute(
name: "DefaultVersionedApi",
routeTemplate: "api/v{version}/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional, version = Config.LatestVersion }
);
我失去了命名我的控制器和功能的所有灵活性。
有没有办法摆脱这种困境?
注意:对于 CustomHttpControlSelector,我在 http://aspnet.codeplex.com/SourceControl/changeset/view/dd207952fa86#Samples/WebApi/NamespaceControllerSelector/NamespaceHttpControllerSelector.cs
上修改了代码我意识到这是一个有点老的问题了,但它可以用 ASP.NET API Versioning package for ASP.NET Web API 来回答。在最新的 3.0 版本中,您可以通过更新配置来实现您的场景:
var constraintResolver = new DefaultInlineConstraintResolver()
{
ConstraintMap =
{
["apiVersion"] = typeof( ApiVersionRouteConstraint )
}
};
configuration.AddApiVersioning(
options =>
{
options.Conventions.Add( new VersionByNamespaceConvention() );
options.AssumeDefaultVersionWhenUnspecified = true;
options.ApiVersionSelector = new CurrentImplementationApiVersionSelector( options );
} );
configuration.MapHttpAttributeRoutes( constraintResolver );
您还应该删除基于约定的路线。如果您使用属性路由,则不需要这些。
您的控制器设置只需更改为:
namespace Web.Controllers.Api.v2
{
[RoutePrefix("api")]
public class LongerThanFooController : ApiController
{
[HttpGet]
[Route("foo/bar")]
[Route("v{version:apiVersion}/foo/bar")]
public string BarFunction()
{
return "foobar";
}
}
}
您需要两个路由定义的原因是您不能在路由模板中间有默认值。默认值只能在最后使用。这也意味着您需要不允许指定任何 API 版本,并指示确定应选择哪个 API 版本的方法是使用当前实现(例如 latest).我个人不喜欢这种方法,因为我认为事情对客户来说应该是可预测的,但这会达到你想要的结果。