WebAPI和ODataController返回406 Not Acceptable

 手机用户2502930273 发布于 2022-12-13 21:45

在将OData添加到我的项目之前,我的路由设置如下:

       config.Routes.MapHttpRoute(
            name: "ApiById",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional },
            constraints: new { id = @"^[0-9]+$" },
            handler: sessionHandler
        );

        config.Routes.MapHttpRoute(
            name: "ApiByAction",
            routeTemplate: "api/{controller}/{action}",
            defaults: new { action = "Get" },
            constraints: null,
            handler: sessionHandler
        );

        config.Routes.MapHttpRoute(
            name: "ApiByIdAction",
            routeTemplate: "api/{controller}/{id}/{action}",
            defaults: new { id = RouteParameter.Optional },
            constraints: new { id = @"^[0-9]+$" },
            handler: sessionHandler

所有控制器都提供Get,Put(操作名称为Create),Patch(操作名称为Update)和Delete.例如,客户端使用这些各种标准URL来表示CustomerType请求:

string getUrl =  "api/CustomerType/{0}";
string findUrl = "api/CustomerType/Find?param={0}";
string createUrl = "api/CustomerType/Create";
string updateUrl = "api/CustomerType/Update";
string deleteUrl = "api/CustomerType/{0}/Delete";

然后我添加了一个OData控制器,其动作名称与我的其他Api控制器相同.我还添加了一条新路线:

        ODataConfig odataConfig = new ODataConfig();

        config.MapODataServiceRoute(
            routeName: "ODataRoute",
            routePrefix: null,
            model: odataConfig.GetEdmModel()
        );

到目前为止,我在客户端没有任何改变.当我发送请求时,我收到406 Not Available错误.

路线混乱了吗?我怎么解决这个问题?

6 个回答
  • 如果您使用的是OData V4,请替换 using System.Web.Http.OData;

    using System.Web.OData;

    在ODataController为我工作.

    2022-12-13 21:51 回答
  • 将routePrefix设置为"api".

    ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
    builder.EntitySet<CustomerType>("CustomerType");
    
    config.MapODataServiceRoute(routeName: "ODataRoute", routePrefix: "api", model: builder.GetEdmModel());
    

    你使用哪个OData版本?System.Web.OData对于V3 ,检查OData V4使用的正确名称空间System.Web.Http.OData.控制器中使用的命名空间必须与WebApiConfig中使用的命名空间一致.

    2022-12-13 21:51 回答
  • 另一件需要考虑的事情是URL区分大小写,因此:

    localhost:xxx/api/Sites -> OK
    localhost:xxx/api/sites -> HTTP 406

    2022-12-13 21:51 回答
  • 我遇到的问题是我已将我的实体集命名为“产品”,并且具有一个ProductController。原来,实体集的名称必须与您的控制器名称匹配。

    所以

    builder.EntitySet<Product>("Products");
    

    使用名为ProductController的控制器将给出错误。

    / api /产品将给出406

    / api /产品将给出404

    因此,使用某些新的C#6功能,我们可以改为:

    builder.EntitySet<Product>(nameof(ProductsController).Replace("Controller", string.Empty));
    

    2022-12-13 21:53 回答
  • 配置路由的顺序具有影响.就我而言,我也有一些标准的MVC控制器和帮助页面.所以在Global.asax:

    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();
        GlobalConfiguration.Configure(config =>
        {
            ODataConfig.Register(config); //this has to be before WebApi
            WebApiConfig.Register(config); 
    
        });
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
    }
    

    当我启动项目并且需要时,过滤器和routeTable部件不存在.

    ODataConfig.cs:

    public static void Register(HttpConfiguration config)
    {
        config.MapHttpAttributeRoutes(); //This has to be called before the following OData mapping, so also before WebApi mapping
    
        ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
    
        builder.EntitySet<Site>("Sites");
        //Moar!
    
        config.MapODataServiceRoute("ODataRoute", "api", builder.GetEdmModel());
    }
    

    WebApiConfig.cs:

    public static void Register(HttpConfiguration config)
    {
        config.Routes.MapHttpRoute( //MapHTTPRoute for controllers inheriting ApiController
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
        );
    }
    

    作为奖励,这是我的RouteConfig.cs:

    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    
        routes.MapRoute( //MapRoute for controllers inheriting from standard Controller
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        );
    }
    

    这必须是那个确切的顺序.我尝试移动调用并最终导致MVC,Api或Odata因404或406错误而中断.

    所以我可以打电话:

    localhost:xxx/ - >导致帮助页面(家庭控制器,索引页面)

    localhost:xxx/api/ - >导致OData $元数据

    localhost:xxx/api/Sites - >导致我的SitesController的Get方法继承自ODataController

    localhost:xxx/api/Test - >导致我继承自ApiController的TestController的Get方法.

    2022-12-13 21:54 回答
  • 我的问题与返回实体模型而不是我暴露的模型(builder.EntitySet<ProductModel>("Products");)有关.解决方案是将实体映射到资源模型.

    2022-12-13 21:54 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有