2012-12-06 52 views
1

我試圖訪問以下網址:的Web API路線沒有映射到正確的URL

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將工作。這意味着有一場比賽。

問題:我對路由的理解是,如果它與第一條路由不匹配,它將回退到第二條路由。我可以理解它是否映射到錯誤的路線,但不應該是指示類似「找不到匹配」的錯誤,無論我如何命令它們。

我錯過了什麼嗎?

回答

4

更新

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

路由匹配從第一路線試圖將集合中的最後 路線。當匹配發生時,不會再有更多的路線被 評估。一般來說,將路由添加到路由屬性,從 到最不具體的路由定義。

您獲得「未找到任何動作」的原因是您的第一條路線匹配。它根本無法找到動作的GET - 因爲你命名你的方法GetByCampaignId

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

所以,你的理解是正確的 - 但是您的網址不符合第一條路線(它只是無法找到動作)。

這將動作映射到你的方法

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

} 

或者乾脆將網址變更爲

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

如何在路徑模型中

取下「獲取」網址。

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

您聲明瞭GetByCampaignId(int campaignId),但沒有[FromUri]屬性,因此campaignId被假定爲在路徑中,即按照此方法匹配/ api/siteapi/1。

如果CAMPAIGNID是隨意改變你的方法簽名如下所示:

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

如果CAMPAIGNID是manditory到您的路線改變你的方法簽名如下所示:

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

我會建議使用此:

http://nuget.org/packages/routedebugger

幫助調試您的路線。

我知道你沒問過,但你的示例URI不是RESTful。

爲了配合第二條路線,你應該嘗試打這個URI:

的http://本地主機:2727/API/SiteApi /獲取/ 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 } 
     ); 
+0

感謝您的插件,我會檢查出 – Jack

2

我認爲你是過於複雜的事情。只需使用默認路由。

您的網址不需要獲取部分:

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

它可以

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

,因爲你的方法已經在它的名字,這意味着它會在響應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) 

當你交換的路由,然後默認路由踢 - 和韓元。

不需要additioanal「DetailedApi」路線,恕我直言。

+0

感謝您的解釋,但我確實需要詳細路線爲更具體的目的 – Jack

0

感謝所有的答案被賦予以上。其中一些非常有趣,但是,這些並不是我正在尋找的東西。

基本上,我的問題不是我應該如何映射URI,而是爲什麼它沒有映射到正確的路線。幸運的是,我在做了一些測試之後找出了答案。

那麼爲什麼「找不到行動」?只是因爲它匹配了我沒有想到的第一條路線。 由於Id設置爲可選,所以它與任何具有兩個參數的路由匹配。這就是爲什麼「SiteAPI」映射到控制器而「Get」映射到Action的原因。由於campaignId處於查詢字符串中,因此在此情況下嘗試映射url時會被忽略。

在我沒有提到的路由中還有其他的東西,但是這應該夠了。如果你想了解更多細節,請參考馬克瓊斯的答案。

+0

我已更新我的答案。 –

相關問題