2012-08-24 38 views
0

我有一個Mvc3項目,其中包括Mvc和Api控制器。當我在未指定「控制器/動作」的情況下運行應用程序時,將選擇「默認」路線並呈現「主頁/索引」頁面。當該頁面運行時,使用url:「api/controller」進行Ajax調用,返回json,然後使用該json填充頁面上的表格。WebApi呼叫失敗,除了默認路由

<script type="text/javascript"> 
    $(function() { 
     var $products = $("#products"); 
     $.ajax({ 
      url: "api/products", 
      contentType: "json", 
      success: function (data) { 
       $.each(data, function (index, item) { 
        $products.append("<tr><td>" + item.ProductCode + "</td>" + 
             "<td>" + item.Description + "</td>"); 
       }); 
      } 
     }); 
    }); 
</script> 

然而,當一個請求到同一個頁面中指定的 「控制器/動作」,如 「本地主機的/ home /指數」 時,Ajax調用被翻譯爲「/home/api/controller」,並且當然由於無法找到ApiController,請求無法完成或返回任何結果。

public static void RegisterRoutes(RouteCollection routes) { 
     routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 

     routes.MapHttpRoute(
      "DefaultApi", 
      "api/{controller}/{id}", 
      new { id = RouteParameter.Optional } 
     ); 

     routes.MapRoute(
      "Default", // Route name 
      "{controller}/{action}/{id}", // URL with parameters 
      new { controller = "Home", action = "Index", id = UrlParameter.Optional } 
     ); 
    } 

考慮到它必須是一個路由的問題,我繼續通過增加一個途徑來解決此問題:

 routes.MapHttpRoute(
      "HomeApi", 
      "home/api/{controller}/{id}", 
      new { id = RouteParameter.Optional } 
     ); 

這是成功的。如同我的下一個變化:

 routes.MapHttpRoute(
      "AnyApi", 
      "{folder}/api/{controller}/{id}", 
      new { id = RouteParameter.Optional } 
     ); 

也可以工作,但讓我有點懷疑它是否是處理在MVC中結合的WebAPI的正確方法。

這是處理這個問題的正確方法嗎?還是有更好的選擇?

回答

1

考慮到它必須是一個路由的問題,我繼續通過增加一個途徑來解決此問題:

不,這根本不是路由問題。你的路線是完全沒有:

public static void RegisterRoutes(RouteCollection routes) { 
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 

    routes.MapHttpRoute(
     "DefaultApi", 
     "api/{controller}/{id}", 
     new { id = RouteParameter.Optional } 
    ); 

    routes.MapRoute(
     "Default", // Route name 
     "{controller}/{action}/{id}", // URL with parameters 
     new { controller = "Home", action = "Index", id = UrlParameter.Optional } 
    ); 
} 

你的問題的事實,你已經在你的JavaScript,而不是使用網址助手生成它硬編碼的URL莖。你絕對應該從來沒有硬編碼ASP.NET MVC應用程序內的網址。你應該總是使用網址助手。

所以:

<script type="text/javascript"> 
    $(function() { 
     var $products = $("#products"); 
     var url = '@Url.RouteUrl("DefaultApi", new { httproute = "", controller = "products" })'; 
     $.ajax({ 
      url: url, 
      success: function (data) { 
       $.each(data, function (index, item) { 
        $products.append("<tr><td>" + item.ProductCode + "</td>" + 
             "<td>" + item.Description + "</td>"); 
       }); 
      } 
     }); 
    }); 
</script> 

還要注意,我從你的AJAX調用刪除contentType: 'json'因爲首先正確的內容類型是在這種情況下,你是不是在請求發送任何數據contentType: 'application/json'和第二,所以你不應該將其設置爲application/json

0

沒有必要添加路由 - 你可以指定API URL,這樣它會一直工作:

/api/controller 

在某些情況下,你可能需要使用Url.RouteUrl助手創建URL明確以在路線上(通過路線名稱和/或路線值)。例如,這將與控制器指定名爲「DefaultApi」路線=產品

@Url.RouteUrl("DefaultApi", new { controller = "products" }) 
+0

'在某些情況下,您可能需要使用Url.RouteUrl助手來創建URL。我寧願說:**在所有情況下**。另請參閱我的答案,瞭解使用Web API路由的正確方法。 –

+0

@DarinDimitrov足夠公平......如果你使用*/api/products *,那麼如果網站被部署到* domain.com/application *,那麼所有像這樣編碼的鏈接將被打破。 – McGarnagle

+1

這只是其中一個原因。另一個重要的原因是你在你的客戶端代碼中假設路由的模式。如果有一天有人決定在'RegisterRoutes'中改變它來說:''mysuperapi- {controller} - {id}「',你現在必須瀏覽所有的視圖並替換'/ api/controller/123 ''用'/ mysuperapi-controller-123'。 –