【发布时间】:2015-12-15 22:05:23
【问题描述】:
我一直在尝试在 Web API 2.2 (5.2.3) 中实现版本化路由,其中在为特定路由选择操作时,较新版本的控制器优先于以前的版本。
例如给定以下控制器类层次结构:
namespace MyApi.Controllers.V1 {
public class FooController {
protected IFooRepository Repo; // Assume Repo is injected via IoC
[Route("{id:int:min(1)}")]
public IFoo GetSingle(int id) {
Repo.Single(new FooSearchOpts { Id = id });
}
public IEnumerable<IFoo> GetAll() {
Repo.Search();
}
}
}
namespace MyApi.Controllers.V3 {
public class FooController : V1.FooController {
public IEnumerable<IFoo> Search(string type) {
Repo.Search(new FooSearchOpts { Type = type });
}
}
}
namespace MyApi.Controllers.V4 {
public class FooController : V3.FooController {
public IEnumerable<IFoo> SearchV4(string type, string name) {
Repo.Search(new FooSearchOpts {
Type = type,
Name = name
});
}
}
}
namespace MyApi.Controllers.V5 {
public class FooController : V4.FooController {
/* nothing relevant */
}
}
我可以通过创建一个自定义的IHttpControllerSelector 来使一些路由工作,该IHttpControllerSelector 从路由数据中读取{version}(例如GET /api/v*/foo/123 总是指向GetSingle)。
当不同版本的控制器有多个可能的路由时,就会出现问题。我需要请求GET /api/v*/foo来选择以下方法:
/api/v1/foo -> V1.FooController.GetAll/api/v2/foo -> V1.FooController.GetAll/api/v3/foo -> V3.FooController.Search/api/v4/foo -> V4.FooController.SearchV4/api/v5/foo -> V5.FooController.SearchV4
只需指定一个自定义控制器选择器就可以理解地抱怨重复/不明确的操作,但是当我指定一个自定义 IHttpActionSelector 时,我找不到任何方法来保留现有的操作选择逻辑。我真的需要手动重新实现所有方法名解析和参数检查的恶作剧,还是有办法利用现有逻辑?
很遗憾,我无法发布我已经拥有的所有内容,但主路由配置看起来像这样:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// VersionedRouteProvider specifies a global route prefix of "api/v{version}/{ctrl}"
config.MapHttpAttributeRoutes(new VersionedRouteProvider());
// VersionedControllerSelector uses {version} and {ctrl} to map out controllers
var controllerSelector = new VersionedControllerSelector(config);
config.Services.Replace(typeof(IHttpControllerSelector), controllerSelector);
// VersionedActionSelector creates actions from controllers,
// currently it would require iterating MethodInfos
// and manually creating all HttpActionDescriptors
// based on the methods' names and parameters
config.Services.Replace(typeof(IHttpActionSelector), new VersionedActionSelector(controllerSelector));
}
}
我已经考虑创建自定义 IDirectRouteProvider 和 IDirectRouteFactory,但似乎我仍然需要自定义 IHttpActionSelector 来处理不明确的路线。
谢谢。
【问题讨论】:
标签: c# asp.net .net asp.net-web-api asp.net-web-api2