OData和WebAPI路由冲突

Mat*_*ves 6 asp.net-mvc routing odata asp.net-web-api

我有一个带有WebAPI控制器的项目.我现在正在添加OData控制器.问题是我的OData控制器与现有的WebAPI控制器具有相同的名称,这导致异常:

Multiple types were found that match the controller named 'Member'. This can happen if the route that services this request ('OData/{*odataPath}') found multiple controllers defined with the same name but differing namespaces, which is not supported. The request for 'Member' has found the following matching controllers: Foo.Bar.Web.Areas.API.Controllers.MemberController Foo.Bar.Web.Odata.Controllers.MemberController
Run Code Online (Sandbox Code Playgroud)

即使控制器位于不同的名称空间并且应该具有可区分的路由,也会发生这种情况.以下是我所拥有的配置的摘要.我该怎么做(除了重命名控制器)以防止此异常?我正在尝试将这些端点公开为:

mysite.com/OData/Members
mysite.com/API/Members/EndPoint
Run Code Online (Sandbox Code Playgroud)

在我看来,URL足够明显,必须有一些方法来配置路由,所以没有冲突.

namespace Foo.Bar.Web.Odata.Controllers {

    public class MemberController : ODataController {
        [EnableQuery]
        public IHttpActionResult Get() {
            // ... do stuff with EF ...
        }
    }
}

namespace Foo.Bar.Web.Areas.API.Controllers {

    public class MemberController : ApiControllerBase {
        [HttpPost]
        public HttpResponseMessage EndPoint(SomeModel model) {
            // ... do stuff to check email ...
        }
    }
}

public class FooBarApp : HttpApplication {

    protected void Application_Start () {
        // ... snip ...

        GlobalConfiguration.Configure(ODataConfig.Register);
        AreaRegistration.RegisterAllAreas();
        RouteConfig.RegisterRoutes(RouteTable.Routes);

        // ... snip ...
    }
}

public static class ODataConfig {
    public static void Register(HttpConfiguration config) {
        config.MapODataServiceRoute(
            routeName: "ODataRoute",
            routePrefix: "OData",
            model: GetModel());
    }

    public static Microsoft.OData.Edm.IEdmModel GetModel() {
        // ... build edm models ...
    }
}

namespace Foo.Bar.Web.Areas.API {
    public class APIAreaRegistration : AreaRegistration {
        public override string AreaName {
            get { return "API"; }
        }

        public override void RegisterArea(AreaRegistrationContext context) {
            var route = context.Routes.MapHttpRoute(
                "API_default",
                "API/{controller}/{action}/{id}",
                new { action = RouteParameter.Optional, id = RouteParameter.Optional }
            );
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

PMo*_*ery 0

您需要在 WebAPI 上包含命名空间约束:

var route = context.Routes.MapHttpRoute(
            name: "API_default",
            routeTemplate: "API/{controller}/{action}/{id}",
            defaults:new { action = RouteParameter.Optional, id = RouteParameter.Optional },
        );
route.DataTokens["Namespaces"] = new string[] {"Foo.Bar.Web.Areas.API.Controllers"];
Run Code Online (Sandbox Code Playgroud)

如果视图控制器发生冲突,您应该能够包含类似的命名空间约束,如下所示:

routes.MapRoute(
            name: "ViewControllers_Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional, area = "" },
            namespaces: new[]{"Foo.Bar.Web.Controllers"}
        );
Run Code Online (Sandbox Code Playgroud)