【问题标题】:Webapi v1 routes are not adhered to不遵守 Webapi v1 路由
【发布时间】:2023-11-29 06:46:01
【问题描述】:

webapi调用返回错误:

  message: "No HTTP resource was found that matches the request URI 'http://localhost:25396/api/dmpe/form/123'.",
  messageDetail: "No action was found on the controller 'Dmpe' that matches the request."

控制器:

   [HttpGet]
    [ActionName("GetForm")]
    public HttpResponseMessage GetForm(long formId)
    {
        try
        {
            var form = this.dmpeService.GetForm(formId);
            return Request.CreateResponse(HttpStatusCode.OK, form);
        }
        catch (Exception e)
        {
            var serializer = new JavaScriptSerializer();
            string json = serializer.Serialize(new { success = false, message = e.Message });
            _logger.Error("GetForm Error: {0}", e.Message);

            return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, json);
        }

    }      

WebApi 路由配置:

   //config.Routes.MapHttpRoute(
   //         name: "GetForm",
   //         routeTemplate: "api/dmpe/form/{id}",
   //         defaults: new
   //         {
   //             controller = "Dmpe",
   //             action = "GetForm"
   //         }
   //     );

更新路线:

  config.Routes.MapHttpRoute(
            name: "GetForm",
            routeTemplate: "api/{controller}/form/{id}"
        );

我的路线基于当前的命名约定。这条路线有效。

   config.Routes.MapHttpRoute(
            name: "GetMenu",
            routeTemplate: "api/forms/menu/{userTypeId}/{ctyhocn}",
            defaults: new
            {
                controller = "Service",
                action = "GetMenu"
            },
            constraints: new { httpMethod = new HttpMethodConstraint(new[] { HttpMethod.Get.ToString() }) }
        );      

现在在 WebApi v2 中,我已经习惯于在控制器中定义路由,如下所示,但这是我正在寻找的 v2 功能。根据当前的示例,我会认为 routeTemplate 会起作用。我查看了我定义的路由的 RouteTables.Routes,它的格式似乎正确:“api/{controller}/form/{id}”

WebApi v2 路由属性

 [HttpGet]
 [AllowAnonymous]
 [Route("api/office/companynames/{searchValue}/")]
 .....

【问题讨论】:

    标签: asp.net-mvc-4 asp.net-web-api ninject


    【解决方案1】:

    您收到的错误消息与路由的配置方式有关,与 Ninject 无关。 WebAPI(1.0 或 2.2)的良好做法是使用以下模板:

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

    与 MVC 不同,没有包含动作名称。

    所以,尝试使用设置的路线,看看你是否可以让它工作。

    【讨论】:

    • 你好@Karen_B 我正在遵循应用程序中当前的 routeTemplate 约定。例如,这是应用程序
       config.Routes.MapHttpRoute( name: "GetMenu", routeTemplate: "api/forms/menu/{userTypeId}/{ctyhocn}", defaults: new { controller = "服务”,动作 = “GetMenu”},约束:新 { httpMethod = new HttpMethodConstraint(new[] { HttpMethod.Get.ToString() }) } );
    • 如果我将 [FromBody] 添加到控制器操作,则使用 routeTemplate...有点...因为它没有获得我在 url (/api/dmpe) 中传递的实际 id /form/123
    • 你试过 [FromUri] 吗?不幸的是,WebAPI v1 没有像 2 那样的路由属性。但是,我确实偶然发现了一些人在 v1 中使用路由属性编写的库。对不起,我没有链接了。
    • 不用担心@Karen_B,我在您的指导下想通了。 v2 用路由属性宠坏了我。谢谢!
    • @WillLopez 我确定你现在已经解决了这个问题,但我想传递一个资源,用于将属性路由添加到 Web API 1。strathweb.com/2012/05/… 我刚刚在我的项目中实现了这个昨天,它似乎运作良好。它处理了我们在 Web API 2.2 中使用的大部分功能,但有一些语法差异。此外,不支持 {id:guid},但仅使用 {id} 似乎可行。 NuGet:“属性路由(ASP.NET WebAPI)”。
    【解决方案2】:

    @Karen_B 为我指明了正确的方向,但我想提供适用的更改,以防其他人遇到此问题。

    我将路由映射更改为:

            config.Routes.MapHttpRoute(
                name: "NewForm",
                routeTemplate: "api/{controller}/form/",
                defaults: new
                {
                    controller = "Dmpe"
                },
                constraints: new { httpMethod = new HttpMethodConstraint(new[] { HttpMethod.Post }) } 
            );
    
            config.Routes.MapHttpRoute(
                name: "GetForm",
                routeTemplate: "api/{controller}/form/{id}",
                defaults: new
                {
                    controller = "Dmpe",
                    id = RouteParameter.Optional
                },
                constraints: new { httpMethod = new HttpMethodConstraint(new[] { HttpMethod.Get }) } 
            );
    

    然后将控制器更改为:

        [HttpPost]
        public HttpResponseMessage Post(DmpeForm form)
        {
           ....
    
    
        [HttpGet]
        public HttpResponseMessage Get(long Id)
        {
        .....
    

    将 http 方法属性添加到方法可能是多余的,因为我更改了方法名称以反映 http 方法,但此时我只想让它工作。如果您有选择,请使用 WebApi 2 :-)

    【讨论】:

    • 感谢您发布最终解决方案。我相信社区中的其他人会觉得它很有帮助。