映射结果时,Web API OData控制器返回“406 - 不可接受”

时间:2015-12-23 18:51:03

标签: asp.net-web-api odata asp.net-web-api2 automapper

我查看了所有SO帖子并没有成功。我可以调用OData控制器并查看检索,映射和打包的数据。控制器方法退出,我得到406 - Not Acceptable。我只使用System.Web.OData命名空间( OData Version v4.0.30319 ),并使用Postman手动设置ContentAccept标题为' application / json '没有运气

也许我在过去的两个小时里错过了一些关于类似问题的每个人的帖子。任何指针都将受到赞赏。

更新 问题似乎出现在 Mapper 代码(Automapper)中,如下面的 Igor 所指出的那样。看起来有承诺返回数据库(EF)实体,而不是映射类。有了这些知识,我发现了这篇SO帖子,但它没有提供解决方案:ApiController vs ODataController when exposing DTOs。我们是否不得不返回数据库实体或者是否可以映射结果?如果是这样,那对我来说是一个交易破坏者。

控制器

[EnableQuery]
[HttpGet]
public async Task<IHttpActionResult> Get()
    {
        var list = await db.ConfigSets.ToListAsync();
        Mapper.CreateMap<ConfigSet, ConfigSetDTO>();
        var configSetDTOs = Mapper.Map<List<ConfigSet>, List<ConfigSetDTO>>(list);
        return Ok(configSetDTOs); //IT LOOKS GOOD HERE!
    }

WebApiConfig:

public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            config.MapHttpAttributeRoutes();
            config.EnableCors();

            // OData - must be before config.Routes when using a prefix. In this case "api"
            config.MapODataServiceRoute("odata", "api", GetEdmModel(), new DefaultODataBatchHandler(GlobalConfiguration.DefaultServer));
            config.EnsureInitialized();

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

        private static IEdmModel GetEdmModel()
        {
            var builder = new ODataConventionModelBuilder();
            builder.Namespace = "Services";
            builder.ContainerName = "DefaultContainer";
            builder.EntitySet<ConfigSet>("Configuration");
            var edmModel = builder.GetEdmModel();
            return edmModel;
        }
    }

2 个答案:

答案 0 :(得分:1)

我从来没有使用oData中的Get()函数和我从SQL视图中提取的EF数据以外的任何东西,所以我不确定什么是可能的或不可能的。据我所知,整个目的是MS Odata Web API控制器根据传入的URL处理所有查询逻辑,这就是为什么你想要使用带有Get方法的oData,因为它提供了一个标准查询数据的方法,没有过滤后端所需的额外代码,并且过滤发生在数据库而不是内存中。如果你在这之间推送像Automapper这样的东西,我怀疑它会有相同的效果。

答案 1 :(得分:1)

旧版本的OData允许您公开任何旧的IQueryable,无论它是否包含数据库对象或DTO。

但是,我可以肯定地说你在这里使用AutoMapper是错误的 - 你在客户端而不是在数据库上进行映射,这仍然允许你返回IQueryable。而不是使用Mapper.Map,使用.ProjectTo&lt;&gt;查询的扩展方法:

Fractional

您也不应该在操作方法中定义地图 - 应该在应用程序启动时定义它们。