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

C# 添加新OData控制器会使现有控制器失败,c#,asp.net-web-api,controller,odata,C#,Asp.net Web Api,Controller,Odata,我正在从两个WebAPI OData示例构建一个示例,它们作为一个单独的项目都可以正常工作。但是,当我添加第二个ODataController类时,该站点就不再工作了,它不再抱怨以前工作过的OData路径模板。详情如下: 只要其控制器(ProductsController)是唯一的控制器,以下操作就可以正常工作: [HttpGet] [ODataRoute("GetSalesTaxRate(state={state})")] public IHttpActionResult GetSalesTa

我正在从两个WebAPI OData示例构建一个示例,它们作为一个单独的项目都可以正常工作。但是,当我添加第二个ODataController类时,该站点就不再工作了,它不再抱怨以前工作过的OData路径模板。详情如下:

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

[HttpGet]
[ODataRoute("GetSalesTaxRate(state={state})")]
public IHttpActionResult GetSalesTaxRate([FromODataUri] string state)
{
    return Ok(GetRate(state));
}
现在,我添加了一个新的控制器(MoviesController),其中包含一些操作

我在Startup类中扩展了Owin,因此它如下所示:

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路径模板 中操作“GetSalesTaxRate”的“GetSalesTaxRate(state={state})” 控制器“产品”不是有效的OData路径模板。资源不是 为段“GetSalesTaxRate”找到

控制器映射到不同的路由(“功能”和“操作”)。问题是每条路线都映射到自己的EDM模型吗

更新。我检查了我可以添加更多控制器,只要它们引用相同的EDM模型。但一旦我引入第二个模型(并从MapODataServiceRoute引用),整个服务就会中断。是否存在支持多个模型的变通方法


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

默认情况下,当映射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<Type> _controllers = new List<Type> { typeof(MetadataController) };

    public CustomAttributeRoutingConvention(IEdmModel model, HttpConfiguration configuration, IEnumerable<Type> 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<Type> controllers)
    {
        var routingConventions = ODataRoutingConventions.CreateDefault();
        routingConventions.Insert(0, new CustomAttributeRoutingConvention(model, configuration, controllers));
        return configuration.MapODataServiceRoute(routeName, routePrefix, model, new DefaultODataPathHandler(),
            routingConventions);
    }
}
公共类启动
{
公共无效配置(IAppBuilder)
{
var config=新的HttpConfiguration();
config.CustomMapODataServiceRoute(routeName:“函数路由”,routePrefix:“函数”,
模型:FunctionStartup.GetEdmModel(),
控制器:新[]{typeof(ProductsController)});
config.CustomMapODataServiceRoute(routeName:“操作路由”,routePrefix:“操作”,
模型:ActionStartup.GetEdmModel(),
控制器:新[]{typeof(MoviesController)};
config.EnsureInitialized();
builder.UseWebApi(配置);
}
}
公共类CustomAttributeRoutingConvention:AttributeRoutingConvention
{
私有只读列表_控制器=新列表{typeof(MetadataController)};
公共CustomAttributeRoutingConvention(IEdmModel模型、HttpConfiguration配置、IEnumerable控制器)
:基本(型号、配置)
{
_控制器。添加范围(控制器);
}
公共覆盖布尔应映射控制器(HttpControllerDescriptor控制器)
{
返回_controllers.Contains(controller.ControllerType);
}
}
公共静态类HttpConfigExt
{
公共静态ODataRoute CustomMapODataServiceRoute(此HttpConfiguration配置,字符串routeName,
字符串routePrefix、IEdmModel模型、IEnumerable控制器)
{
var routingConventions=ODataRoutingConventions.CreateDefault();
routingConventions.Insert(0,新的CustomAttributeRoutingConvention(模型、配置、控制器));
返回configuration.MapODataServiceRoute(routeName、routePrefix、model、新的DefaultODataPathHandler(),
路由公约);
}
}