2

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

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

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

“'ObjectContent`1' 类型无法序列化内容类型 'application/json;odata=minimalmetadata;streaming=true;charset=utf-8' 的响应正文。”

除了内部的例外

无法从 OData 路径中找到相关实体集。序列化payload需要相关实体集

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

任何帮助,将不胜感激。

这是一些代码:

全球.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;
        }

自定义HttpControllerSelector:

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

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;
        }
4

1 回答 1

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 }
);

注意:截至目前,将此作为答案发布,但如果有人有更好的解释,我会检查一下。:)

于 2013-09-12T04:38:11.677 回答