使用自定义路由实现ODataController将返回“无法从OData路径中找到相关实体集”错误

时间:2013-09-03 13:15:10

标签: c# json asp.net-web-api odata

我正在尝试从我们当前的ApiController实现转移到ODataController,因为这是我发现可以启用返回OData Json格式数据的唯一方法。 (与问题here相同,但解决方案对我不起作用)

我一直在尝试锻炼ODataController,我发现它在this之后运行良好。但是,我的项目实现了与简单的“〜/ odata / Entity”的默认OData路由不同的路由。我需要将控制器分组到区域,因为有些控制器在名称中重复。

关注thisthis,我能够实现自定义路由并运行它似乎到达正确的控制器并成功通过它。但是,我仍然在Fiddler中遇到错误

  

“'ObjectContent`1'类型无法序列化响应正文   内容类型'application / json; odata = minimalmetadata;流= TRUE;   字符集= UTF-8' 。“

内部例外

  

无法从OData路径找到相关实体集。该   相关实体集是序列化有效载荷

所必需的

现在我已经被困了好几个小时了。没有路由处理程序,只需通过“〜/ odata / Entity”访问数据,我的代码就可以运行得很好。就在我实现自定义路由时,它在通过我的控制器代码后失败了。

任何帮助都将不胜感激。

以下是一些代码:

的Global.asax:

            //Added this on App_Start
            config.Services.Replace(typeof(IHttpControllerSelector), new CustomHttpControllerSelector(config)); 

            //Snippet from RegisterRoutes
            ODataConventionModelBuilder modelBuilder = new ODataConventionModelBuilder();
            modelBuilder.EntitySet<Entity>("Entities");
            IEdmModel model = modelBuilder.GetEdmModel();

            config.Routes.MapODataRoute(
                routeName: "ODataDefault",
                routePrefix: "{version}/{area}/{controller}",     //Works since I could reach my controller
                model: model);

控制器:

        [HttpGet]
        [Queryable(AllowedQueryOptions = AllowedQueryOptions.All)]
        public IQueryable<Entity> Get()
        {
            EntitySet entitySet = new EntitySet();
            return entitySet.Entities;
        }

CustomHttpControllerSelector:

继承自this。基本上,这只是解析请求以获取特定的控制器描述符。

private HttpControllerDescriptor GetController(HttpRequestMessage request)
        {
            HttpControllerDescriptor descriptor = null;

            IHttpRouteData routeData = request.GetRouteData();

            // Get variables from the route data.
            string versionName = null;
            routeData.Values.TryGetValue("version", out versionName );

            string areaName = null;
            routeData.Values.TryGetValue("area", out areaName);

            string controllerName = null;
            routeData.Values.TryGetValue("controller", out controllerName);

            string fullName = string.Format(CultureInfo.InvariantCulture, "{0}.{1}.{2}", versionName, areaName, controllerName);

            // Search for the controller.
            // _controllerTypes is a list of HttpControllerDescriptors
            var type = _controllerTypes.Where(t => t.Key.EndsWith(fullName, StringComparison.OrdinalIgnoreCase)).Select(t => t.Value).FirstOrDefault();

            if (type != null)
            {
                descriptor = new HttpControllerDescriptor(_configuration, controllerName, type);
            }

            return descriptor;
        }

1 个答案:

答案 0 :(得分:2)

最终通过删除routePrefix的{controller}部分并实现自定义 IODataRoutingConvention 来解决此问题,以便在路由的初始解析未检测到控制器时输入默认控制器值值。代码如下:

public string SelectController(ODataPath odataPath, HttpRequestMessage request)
{
     string controllerName = ""

     //do stuff here to select controller

     return controllerName;
}

我猜这是ApiController地图路由中默认和约束参数的长期替代

RouteTable.Routes.MapHttpRoute(
    name: "RouteName",
    routeTemplate: "{version}/{area}/{controller}",
    defaults: new { controller = controllerName },
    constraints: new { version = v1 }
);

注意:现在发布此答案,但如果有人有更好的解释,我会检查一下。 :)