【问题标题】:Web API route not mapped to the correct urlWeb API 路由未映射到正确的 url
【发布时间】:2012-11-23 23:58:06
【问题描述】:

我正在尝试访问以下网址:

http://localhost:2727/api/SiteApi/Get?campaignId=2

这里是配置:

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

动作试图映射到

public class SiteApiController : ApiController
{
    ...
    public IEnumerable<Site> GetByCampaignId(int campaignId)
    {
        ...
        return sites;   
    }      
}

目前返回“未找到任何操作”。但是,如果交换路线的顺序,Url 将起作用。这意味着有一场比赛。

问题:我对路由的理解是,如果不匹配第一个路由,就会回退到第二个路由。我可以理解它是否映射到错误的路线,但无论我如何订购它们,它都不应该是指示“未找到匹配”之类的错误。

我错过了什么吗?

【问题讨论】:

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


    【解决方案1】:

    感谢上面给出的所有答案。其中一些很有趣,但是,那些并不是我真正想要的。

    基本上,我的问题不是我应该如何映射 URI,而是为什么它没有映射到正确的路由。幸运的是,经过一些测试,我已经找到了答案。

    那么为什么“未找到任何操作”?仅仅因为它匹配了我没想到的第一条路线。 因为 Id 设置为可选,所以它匹配任何带有两个参数的路由。这就是为什么“SiteAPI”映射到控制器而“Get”映射到 Action。由于campaignId 在查询字符串中,因此在这种情况下尝试映射url 时会被忽略。

    我没有提到路由中的其他点点滴滴,但这应该足够了。如果您想了解更多详细信息,请参阅 Mark Jones 的回答。

    【讨论】:

      【解决方案2】:

      更新

      好资源:http://msdn.microsoft.com/en-us/library/cc668201(v=vs.100).aspx

      从第一个路由到最后一个路由匹配 集合中的路线。当匹配发生时,不再有路由 评估。通常,将路由添加到 Routes 属性中的顺序是 最具体的路由定义到最不具体的路由定义。

      您获得“未找到任何操作”的原因是您的第一条路线匹配。它根本找不到操作 Get - 因为您已将方法命名为 GetByCampaignId

      http://localhost:2727/api/SiteApi/Get?campaignId=2
      

      所以您的理解是正确的 - 但是您的 URL 确实与第一个路由匹配(它只是找不到操作)。

      这会将操作映射到您的方法

      [ActionName("Get")]
      public IEnumerable<Site> GetByCampaignId(int campaignId)
      {
      
      }
      

      或者干脆把你的网址改成

      http://localhost:2727/api/SiteApi/GetByCampaignId?campaignId=2
      

      如何为您的路线建模

      从网址中删除“获取”。

      您似乎希望在查询字符串中指定campaignId。

      您已经声明了没有 [FromUri] 属性的 GetByCampaignId(intcampaignId),因此假定该campaignId 在路径中,即目前该方法与/api/siteapi/1 匹配。

      如果campaignId 是可选的,像这样改变你的方法签名:

      public IEnumerable<Site> GetByCampaignId([FromUri]int? campaignId = null)
      {
          if(campaignId.HasValue)
          {
             //....
          }
          return sites;   
      }   
      

      如果campaignId 对您的路线是强制性的,请更改您的方法签名,如下所示:

      public IEnumerable<Site> GetByCampaignId([FromUri]int campaignId)
      {
          return sites;   
      }   
      

      【讨论】:

        【解决方案3】:

        我认为你把事情复杂化了。使用默认路由即可。

        您的 URL 不需要 Get 部分:

        http://localhost:2727/api/SiteApi/Get?campaignId=2
        

        可以

        http://localhost:2727/api/SiteApi/?campaignId=2
        

        因为您的方法名称中有 Get,这意味着它将响应 HTTP GET 请求(约定很好:http://www.asp.net/web-api/overview/web-api-routing-and-actions/routing-in-aspnet-web-api)。它会看到动作参数“campaignId”并说“啊哈,我会去那个动作”

        public IEnumerable<Site> GetByCampaignId(int campaignId)
        

        当您交换路线时,默认路线会启动 - 并获胜。

        不需要额外的“DetailedApi”路由,恕我直言。

        【讨论】:

        • 感谢您的解释,但我确实需要详细路线以用于更具体的目的
        【解决方案4】:

        我会推荐使用这个:

        http://nuget.org/packages/routedebugger

        帮助调试您的路线。

        我知道你没有问,但你的示例 URI 不是 RESTful。

        要匹配第二个路由,你应该尝试点击这个 URI:

        http://localhost:2727/api/SiteApi/Get/2

        您的第一个映射不应捕获此路线,因为没有“2”操作,它会退回到第二个映射。但是,我可以看到这会造成麻烦:我不会使用您的映射。恕我直言,您正在尝试实现与以下相同的效果:

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

        【讨论】:

        • 感谢插件,我去看看
        猜你喜欢
        • 2012-11-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-03-29
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多