ODataController 返回 HTTP 406 不可接受的错误。

9

我正在使用Web API 2.2构建OData 3服务。

该服务正确返回实体的元数据,但在查询实际实体时返回406不可用。我已经做了很多研究(目前正在跟随几个教程),但我没有找到任何真正有效的解决方法。

这是我的WebApiConfig:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;
using System.Web.OData.Builder;
using System.Web.OData.Extensions;

namespace MyProject
{
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            ODataModelBuilder builder = new ODataConventionModelBuilder();

            builder.EntitySet<MarvelCharacter>("MarvelCharacters");
            config.MapODataServiceRoute(
                routeName: "Marvel",
                routePrefix: "dude",
                model: builder.GetEdmModel());
        }
    }
}

我的控制器(不完整,但你可以理解):

using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using System.Web.Http.OData;
using System.Web.Http.OData.Query;
using Microsoft.Data.OData;
using MyProject;

namespace MyProject.Controllers
{
    public class MarvelCharactersController : ODataController
    {
        private static ODataValidationSettings _validationSettings = new ODataValidationSettings();

        // GET: odata/MarvelCharacters
        public IHttpActionResult GetMarvelCharacters(ODataQueryOptions<MarvelCharacter> queryOptions)
        {
            // validate the query.
            try
            {
                queryOptions.Validate(_validationSettings);
            }
            catch (ODataException ex)
            {
                return BadRequest(ex.Message);
            }

            var entities = new myEntities();
            var marvelCharacters = (from c in entities.MarvelCharacters select c).ToList();

            return Ok<IEnumerable<MarvelCharacter>>(marvelCharacters);
        }
    }
}
1个回答

27
结果证明,这个问题的答案非常简单,但是我找不到任何覆盖范围广泛的文档。我试图在WebAPI 2.2上实现一个OData 3端点。我遵循了几个不同的教程,其中一些是关于OData 3的,另一些是关于OData 4的。我在我的WebApiConfig中使用了OData 4(System.Web.OData),在我的控制器中使用了OData 3 (System.Web.Http.OData)。结果发现它们不能很好地协同工作。为了增加一些价值,并且因为我已经混合使用了两者,我决定通过别名设置命名空间,并创建版本化的控制器来支持版本3和版本4。WebApiConfig:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;
using ODataV3 = System.Web.Http.OData;
using ODataV4 = System.Web.OData;

namespace MyProject
{
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            // OData V3 Route

            ODataV3.Builder.ODataModelBuilder builder3 = new ODataV3.Builder.ODataConventionModelBuilder();

            builder3.EntitySet<MarvelCharacter>("MarvelCharactersV3");
            // The MapODataRoute function is deprecated in WebAPI 2.2,
            // but I haven't found an alternative for supporting OData 3.
            config.Routes.MapODataRoute(
                routeName: "Marvel3",
                routePrefix: "dude3",
                model: builder3.GetEdmModel());

            // ODate V4 Route

            ODataV4.Builder.ODataModelBuilder builder4 = new ODataV4.Builder.ODataConventionModelBuilder();

            builder4.EntitySet<MarvelCharacter>("MarvelCharactersV4");
            ODataV4.Extensions.HttpConfigurationExtensions.MapODataServiceRoute(
                configuration: config,
                routeName: "Marvel4",
                routePrefix: "dude4",
                model: builder4.GetEdmModel());
        }
    }
}

漫威角色V3(OData 3):

using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using System.Web.Http.OData; // OData V3
using System.Web.Http.OData.Query;
using Microsoft.Data.OData;
using MyProject;

namespace MyProject.Controllers
{
    public class MarvelCharactersV3Controller : ODataController
    {
        private static ODataValidationSettings _validationSettings = new ODataValidationSettings();

        // GET: odata/MarvelCharacters
        public IHttpActionResult GetMarvelCharactersV3(ODataQueryOptions<MarvelCharacter> queryOptions)
        {
            // validate the query.
            try
            {
                queryOptions.Validate(_validationSettings);
            }
            catch (ODataException ex)
            {
                return BadRequest(ex.Message);
            }

            var entities = new myEntities();
            var marvelCharacters = (from c in entities.MarvelCharacters select c).ToList();

            return Ok<IEnumerable<MarvelCharacter>>(marvelCharacters);
        }
    }
}

MarvelCharactersV4 (OData 4):

using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using System.Web.OData; // OData 4
using System.Web.OData.Query;
using Microsoft.Data.OData;
using MyProject;

namespace MyProject.Controllers
{
    public class MarvelCharactersV4Controller : ODataController
    {
        private static ODataValidationSettings _validationSettings = new ODataValidationSettings();

        // GET: odata/MarvelCharacters
        public IHttpActionResult GetMarvelCharactersV4(ODataQueryOptions<MarvelCharacter> queryOptions)
        {
            // validate the query.
            try
            {
                queryOptions.Validate(_validationSettings);
            }
            catch (ODataException ex)
            {
                return BadRequest(ex.Message);
            }

            var entities = new myEntities();
            var marvelCharacters = (from c in entities.MarvelCharacters select c).ToList();

            return Ok<IEnumerable<MarvelCharacter>>(marvelCharacters);
        }
    }
}

这可能不是最好的架构(我可能会创建一个库来整合控制器之间的类似代码),但我已经进行了测试并可以成功地通过OData 3和OData 4进行查询,所以现在我对它感到满意。


9
我很希望微软实际上使用“OdataV3”和“OdataV4”名称空间,而不是将新版本零散地塞在这里那里。为别名点赞-好主意。 - bkwdesign
我遇到了同样的问题,最初使用oData v3进行设置,后来转移到oData v4,使用V4创建的控制器开始出现406错误。重新使用V3创建一个控制器以验证问题,是的,它开始工作了。现在正在升级到V4。 - Zafar
1
非常感谢您! - Jonathan Quinth
非常感谢JDB。微软的命名空间分配很混乱,文档也不够清晰。 - Andy Horton

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接