添加新的OData控制器会使现有控制器失败

我正在从两个Web API OData示例构建一个示例,每个示例都可以作为一个单独的项目正常工作。 但是当我添加第二个ODataController类时,该站点不再适用于以前工作的OData路径模板。 这里有更多细节:

只要其控制器(ProductsController)是唯一的控制器,以下操作就可以正常工作:

[HttpGet] [ODataRoute("GetSalesTaxRate(state={state})")] public IHttpActionResult GetSalesTaxRate([FromODataUri] string state) { return Ok(GetRate(state)); } 

现在我添加了一个带有一些动作的新控制器(MoviesController)。

我扩展了Owin Startup类,所以它看起来像这样:

 public void Configuration(IAppBuilder builder) { var config = new HttpConfiguration(); config.MapODataServiceRoute(routeName: "functions route", routePrefix: "functions", model: FunctionStartup.GetEdmModel()); config.MapODataServiceRoute(routeName: "actions route", routePrefix: "actions", model: ActionStartup.GetEdmModel()); builder.UseWebApi(config); } 

但是,当我尝试执行Web请求(URLBASE / functions / $ metadata)时,出现以下错误:

System.InvalidOperationException控制器“Products”中的操作“GetSalesTaxRate”上的路径模板“GetSalesTaxRate(state = {state})”不是有效的OData路径模板。 找不到段“GetSalesTaxRate”的资源。

控制器映射到不同的路由(“function”和“操作”)。 可能是问题是每条路线都映射到自己的EdmModel?

UPDATE。 我检查过我可以添加更多控制器,只要它们引用相同的EDM模型即可。 但是,一旦我引入第二个模型(并从MapODataServiceRoute引用它),整个服务就会中断。 有没有解决方法来支持多个模型?

更新2.如果我inheritanceDefaultHttpControllerTypeResolver并且只启用单个控制器(其中任何一个),那么也可以正常工作。 但我仍然感到疑惑为什么使用不同型号的多个控制器都会失败。

默认情况下,当映射OData属性路由约定时,HTTP控制器选择器IHttpControllerSelector的默认逻辑使用HttpConfiguration的DefaultAssembloesResolver,它将查找应用程序域中的所有控制器类型。 范围可以简化为属于模型的控制器。

我们可以自定义MapODataServiceRoute扩展方法。 一些代码片段:

 public class Startup { public void Configuration(IAppBuilder builder) { var config = new HttpConfiguration(); config.CustomMapODataServiceRoute(routeName: "functions route", routePrefix: "functions", model: FunctionStartup.GetEdmModel(), controllers: new[] { typeof(ProductsController) }); config.CustomMapODataServiceRoute(routeName: "actions route", routePrefix: "actions", model: ActionStartup.GetEdmModel(), controllers: new[] { typeof(MoviesController) }); config.EnsureInitialized(); builder.UseWebApi(config); } } public class CustomAttributeRoutingConvention : AttributeRoutingConvention { private readonly List _controllers = new List { typeof(MetadataController) }; public CustomAttributeRoutingConvention(IEdmModel model, HttpConfiguration configuration, IEnumerable controllers) : base(model, configuration) { _controllers.AddRange(controllers); } public override bool ShouldMapController(HttpControllerDescriptor controller) { return _controllers.Contains(controller.ControllerType); } } public static class HttpConfigExt { public static ODataRoute CustomMapODataServiceRoute(this HttpConfiguration configuration, string routeName, string routePrefix, IEdmModel model, IEnumerable controllers) { var routingConventions = ODataRoutingConventions.CreateDefault(); routingConventions.Insert(0, new CustomAttributeRoutingConvention(model, configuration, controllers)); return configuration.MapODataServiceRoute(routeName, routePrefix, model, new DefaultODataPathHandler(), routingConventions); } }