Web API路由未映射到正确的URL

时间:2012-12-06 01:16:52

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

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

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;   
    }      
}

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

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

我错过了什么吗?

4 个答案:

答案 0 :(得分:4)

<强>更新

资源良好: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(int campaignId),因此假定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;   
}   

答案 1 :(得分:2)

我认为你过于复杂。只需使用默认路由。

您的网址不需要获取部分:

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”路线,imho。

答案 2 :(得分:1)

我建议使用它:

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 }
        );

答案 3 :(得分:0)

感谢上面给出的所有答案。其中一些非常有趣,但是,这些并不是我想要的。

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

为什么“找不到行动”?仅仅因为它与第一条路线相匹配,这是我没想到的。 因为Id设置为可选,所以它匹配任何具有两个参数的路由。这就是“SiteAPI”映射到控制器和“Get”映射到Action的原因。由于campaignId位于查询字符串中,因此在尝试映射网址时会被忽略。

路由中还有其他部分,我没有提及,但这应该足够了。如果您想了解更多细节,请参阅Mark Jones的答案。

相关问题