将OData方法范围限定为单个控制器的正确方法是什么?

时间:2017-09-11 20:45:13

标签: asp.net-mvc asp.net-web-api routing odata

我在同一个项目中使用WebApi 2控制器与单个OData控制器并排工作。尝试设置所需的路由配置:

  • / api 的所有请求都应映射到此ODataController
  • 所有其他请求应指向普通的Web Api控制器

当我尝试将 / api 路线映射到OData控制器时,如下所示:

class WebApiConfig
{
  public static void Register(HttpConfiguration configuration)
  {
    configuration.Routes.MapHttpRoute("API Default", "api/{action}/{id}",
        new { controller = "ApiOdata", id = RouteParameter.Optional });

    ODataModelBuilder builder = new ODataConventionModelBuilder();
    builder.EntitySet<Organization>("Organizations");
     configuration.Routes.MapODataServiceRoute(
        routeName: "ODataRoute",
        routePrefix: "Api",
        model: builder.GetEdmModel());
   }
}

所有方法调用都适用于Web Api和OData控制器,但 / api / $ metadata 等请求不起作用。

当我删除“API Default”路径时 - 对OData控制器方法的请求 / api / Organizations 停止工作(返回404),但 / api / $ metadata 开始

404详细错误消息:

<Error>
 <Message>
  No HTTP resource was found that matches the request URI 'http://localhost:53576/api/Organizations'.
 </Message>
 <MessageDetail>
   No type was found that matches the controller named 'Organizations'.
 </MessageDetail>
</Error>

将所有OData调用映射到单个控制器操作的正确方法是什么?

1 个答案:

答案 0 :(得分:0)

最后结束了自定义路由约定。为它添加了类:

public class CustomControllerRoutingConvention : IODataRoutingConvention
{
    public string SelectAction(System.Web.OData.Routing.ODataPath odataPath, HttpControllerContext controllerContext, ILookup<string, HttpActionDescriptor> actionMap)
    {
        if (odataPath.PathTemplate.StartsWith("~/entityset") 
            || odataPath.PathTemplate.StartsWith("~/unboundfunction"))
        {
            return odataPath.Segments[0].Identifier;
        }
        // Not a match.
        return null;    
    }

    public string SelectController(System.Web.OData.Routing.ODataPath odataPath, HttpRequestMessage request)
    {
        if (!odataPath.PathTemplate.Contains("$metadata"))
        {
            if (odataPath.PathTemplate != "~")
            {
                return "ApiOdata";
            }
        }
        return null;
    }
}

并在WebApiConfig.cs的Register方法中使用它:

public static void Register(HttpConfiguration configuration)
{
  ...
  IList<IODataRoutingConvention> routingConventions =  ODataRoutingConventions.CreateDefault();
    routingConventions.Insert(0, new CustomControllerRoutingConvention());

    configuration.MapODataServiceRoute(
        routeName: "ODataRoute",
        routePrefix: "Api",
        pathHandler: new DefaultODataPathHandler(),
        routingConventions: routingConventions,
        model: builder.GetEdmModel());
}

它不是完美的解决方案,不会为每个OData请求提供服务(只有元数据,实体集和未绑定的功能,例如&#34; api / Organizations&#34;)但它足够用于处理像o.js和Simple.Odata.Client这样的客户端。 此外,它允许避免控制器弄乱和膨胀我的项目。