【问题标题】:Troubleshoot to trigger web api action method疑难解答触发 web api 动作方法
【发布时间】:2016-08-22 11:36:26
【问题描述】:

我在做我的 web api 项目。

我在控制器中有两个 get 操作方法。

这里是控制器:

namespace Playground.Web.Controllers.API
{
    [RoutePrefix("api/DamageEvent/{actionType}")]
    public class DamageEventController : ApiController
    {
        #region API methods
        [HttpGet]
        public async Task<IHttpActionResult> GetDamageEvent(int damageEventId = 0)
        {
           //some logic 
        }
        [HttpGet]
        [Route("{ddd:int}")]
        public async Task<IHttpActionResult> GetDamageEvent2(int ddd = 0)
        {
           //some logic 
        }
        #endregion
    }
}

这里WebApiConfig定义:

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        // Web API configuration and services

        // Web API routes
        config.MapHttpAttributeRoutes();

        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );
        config.Formatters.JsonFormatter.SerializerSettings.DateFormatString = "dd/MM/yyyy";
    }
}

这里是在 fiddler compose 中触发 web api 动作的 URL 示例:

http://localhost/playground/api/DamageEvent/GetDamageEvent2/?ddd=22

我希望 GetDamageEvent2 web api 操作对于上面的 URL 将被触发。但是GetDamageEvent action 方法被触发了。

为什么没有触发 GetDamageEvent2?知道我缺少什么吗?

===============================更新========= ========================

在我得到 Nkosi

的红色回答之后

我对我的代码做了一些更改,我在类 WebApiConfig 中添加了新路由:

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

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

这里是动作类型的变化:

namespace Playground.Web.Controllers.API
{
    [RoutePrefix("api/DamageEvent")]
    public class DamageEventController : ApiController
    {
        #region API methods
        [HttpGet]
        [Route("GetDamageEvent/{damageEventId}")]
        public async Task<IHttpActionResult> GetDamageEvent(int damageEventId = 0)
        {
           //some logic 
        }
        [HttpGet]
        [Route("GetDamageEvent2/{ddd}")]
        public async Task<IHttpActionResult> GetDamageEvent2(int ddd = 0)
        {
           //some logic 
        }
        #endregion
    }
}

在进行上述更改后,我尝试触发这两个操作并且它起作用了。

但现在的问题是当我尝试在另一个控制器中调用另一个动作时,例如:

http://localhost/playground/api/Contracts/1

我收到 404 错误。

所以我猜这个错误是因为新的路由模板。

所以我的问题是如何解决上述错误并仅在 URI 尝试访问 DamageEventController 时才考虑新的路由模板?

【问题讨论】:

  • 您必须向控制器展示不工作的情况,否则我们将假设它为什么不工作。
  • 好的,我重新阅读了新问题,这可能是您路线的订购问题。框架使用第一个匹配的路由。尝试切换两个基于约定的路线的顺序。
  • @Nkosi ,我切换了路由顺序模板。当我尝试访问 DamageEvent 控制器时,我收到 405 错误。
  • 您添加的新会议路线。除了DamageEventController,您还需要它吗?如果没有,那么您可以安全地删除该路由并保留您的默认值,因为 DamageEventController 正在完全使用属性路由。
  • @Nkosi 你的意思是来自 WebApiConfig 的 actionAPI?

标签: asp.net-web-api asp.net-web-api2 asp.net-web-api-routing


【解决方案1】:

您正在混合使用属性路由和基于约定的路由。

没有任何内容与您的 RoutePrefix 匹配,因为控制器中没有任何操作同时具有 {actionType} {ddd} 模板。

但是您声明的网址...

api/DamageEvent/GetDamageEvent2/?ddd=22

...匹配路由表中GetDamageEvent 的基于DefaultApi 约定的路由,因为它没有[RouteAttribute],并且默认返回约定...

api/{controller=DamageEvent}/{id=GetDamageEvent2/?ddd=22}

查看Routing in ASP.NET Web API 以了解基于约定的路由。

还有Attribute Routing in ASP.NET Web API 2

路由表中的每个条目都包含一个路由模板。默认 Web API 的路由模板是“api/{controller}/{id}”。在这个 模板,“api”是文字路径段,{controller} 和 {id} 是占位符变量。

当 Web API 框架收到一个 HTTP 请求时,它会尝试匹配 针对路由表中的路由模板之一的 URI。如果不 路由匹配,客户端收到 404 错误。例如, 以下 URI 匹配默认路由:

/api/DamageEvent
/api/DamageEvent/1
/api/DamageEvent/GetDamageEvent2/?ddd=22

一旦找到匹配的路由,Web API 就会选择控制器和 行动:

  • 为了找到控制器,Web API 将“Controller”添加到 {controller} 变量的值中。
  • 要查找操作,Web API 会查看 HTTP 方法,然后查找名称以该 HTTP 方法名称开头的操作。为了 例如,对于 GET 请求,Web API 会查找启动的操作 使用“Get...”,例如 “GetDamageEvent”。这 约定仅适用于 GET、POST、PUT 和 DELETE 方法。你可以 通过使用控制器上的属性来启用其他 HTTP 方法。 我们稍后会看到一个例子。
  • 路由模板中的其他占位符变量(例如 {id})映射到操作参数。

要使您声明的路线正常工作,您需要更新您的路线模板。属性路由或向路由表添加新的约定路由

【讨论】:

  • 感谢您的回答。它帮助我理解了一些观点。但不幸的是,在添加新的路由模板时,对其他控制器中其他操作的其他 URI 查询会造成麻烦。我更新了我的问题。请检查我的更新。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-06-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-06
  • 2014-08-29
相关资源
最近更新 更多