暴露ApiControllers和ODataControllers时如何处理重复的路由?

时间:2014-12-30 16:11:15

标签: .net c#-4.0 asp.net-mvc-routing odata asp.net-web-api2

我有一个WebApi2项目,它公开了一个ApiController和一个ODataController。不幸的是,可以通过两个URL访问OData控制器。一个是“api / Dogs”,另一个是“odata / Dogs”这是因为我同时调用了MapHttpRoute和MapODataserviceRoute。 “api / Dogs”实际上是实例化控制器,运行Get方法,但返回带有空白结果的HTTP 406。我希望“api / Dogs”URI返回404,甚至不运行实例化控制器并运行该方法。这样做的最佳方式是什么?

到目前为止,我已经提出了3种可能的方法,尽管到目前为止我只尝试过#1。在我继续前进之前,我正在寻找反馈。 1)我可以使用IgnoreRoute()显式忽略该路由。 2)我可以为MapHttpRoute()调用编写一个约束来检查控制器是否是ODataController。这是可能的,但似乎它会涉及反射,可行但有点凌乱。 3)消除对MapHttpRoute()的调用并使用属性路由。我还没有尝试过属性路由:这有意义吗?

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        // Web API configuration and services

        // Web API routes
        config.MapHttpAttributeRoutes();

        // I could explicitly ignore the route.
        //config.Routes.IgnoreRoute("RedundantRouteCuzOfOData", "api/Dogs");

        // Standard routing
        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional },
        );

        ODataModelBuilder builder = new ODataConventionModelBuilder();
        builder.EntitySet<Dog>("Dogs");
        config.MapODataServiceRoute(
            routeName: "ODataRoute",
            routePrefix: "odata",
            model: builder.GetEdmModel());
    }
}

public class DogsController : ODataController
{
   protected override void Initialize(System.Web.Http.Controllers.HttpControllerContext controllerContext)
   {
       base.Initialize(controllerContext);
       Console.WriteLine("DogsController Initialized");
   }

   TestEntities _ef;

   [EnableQuery]
   public IQueryable<Dog> Get()
   {
       return Get(null);
   }

   [EnableQuery]
   // [Queryable(PageSize=10)] <-- Deprecated in oData v3 in favor of EnableQuery, see http://www.asp.net/web-api/overview/releases/whats-new-in-aspnet-web-api-22
   public IQueryable<Dog> Get(Guid? kennelId)
   {
       // Yes: The constructor for the entities takes a string.  I know that is odd,
       // but it tells the EF which database to connect to.
       _ef = new TestEntities(kennelId == null ? null : kennelId.ToString());
       var results = _ef.Dogs;
       return (IQueryable<Dog>)results;
   }

   protected override void Dispose(bool disposing)
   {
       _ef.Dispose();
       base.Dispose(disposing);
   }

}

0 个答案:

没有答案