我正在尝试访问以下网址:
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将起作用。这意味着有一场比赛。
问题:我对路由的理解是,如果它与第一条路线不匹配,它将回退到第二条路线。我可以理解它是否映射到错误的路线,但它不应该是一个错误,表示“找不到匹配”,无论我如何订购它们。
我错过了什么吗?
答案 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的答案。