2011-07-13 50 views
10

行動上控制器類型「索引」的當前請求「UsersController」是以下動作的方法之間曖昧: System.Web.Mvc.ActionResult PostUser(Models.SimpleUser)上型Controllers.UsersController 的System.Web。 Mvc.ActionResult PostUser(的Int32,Models.SimpleUser)的類型Controllers.UsersController當我嘗試後website.com/users/與表單值儘管參數不同,爲什麼這兩個操作被認爲是不明確的?

正在發生的事情。

當沒有ID(website.com/users/)時,我希望它創建一個新用戶,當有一個ID(例如/ users/51)時,我希望它更新該用戶,那麼如何才能我讓它告訴這兩個行動之間的區別?

這裏有兩個動作:

[HttpPost] 
    [ActionName("Index")] 
    public ActionResult PostUser(SimpleUser u) 
    { 

     return Content("User to be created..."); 
    } 

    [HttpPost] 
    [ActionName("Index")] 
    public ActionResult PostUser(int id, SimpleUser u) 
    { 

     return Content("User to be updated..."); 
    } 

這裏是圖路線:

routes.MapRoute(
     "Users", 
     "users/{id}", 
     new { controller = "Users", action = "Index" } 
    ); 
+0

我在http:// stackoverflow上提出了同樣的問題。com/questions/6479631/why-cant-asp-net-mvc-differences-between-two-actions-when-they-have-different-pa – KallDrexx

回答

8

主要問題是您的兩個操作方法之間存在一些不明確的地方,因爲模型綁定不能幫助識別路由配置。您當前的路由只是指向索引方法。

您仍然可以擁有相同的網址,但以不同的方式命名您的操作並應用一些新路線會很有幫助。

[HttpPost] 
public ActionResult Create(SimpleUser u) 
{ 
    return Content("User to be created..."); 
} 

[HttpPost] 
public ActionResult Edit(int id, SimpleUser u) 
{ 
    return Content("User to be updated..."); 
} 

然後在你的路由嘗試

routes.MapRoute(
    "UserEdit", 
    "users/{id}", 
    new { controller = "Users", action = "Edit", 
     httpMethod = new HttpMethodConstraint("POST") }); 

routes.MapRoute(
    "UserCreate", 
    "users", 
    new { controller = "Users", action = "Create", 
     httpMethod = new HttpMethodConstraint("POST") }); 

的路由將被限制爲只發布的事件,這意味着你還可以添加一些路由在同一路線上的GET方法。如列表或其他東西。

+0

我很好奇它爲什麼不檢測/ {id},因此選擇採用該id的Action。我想我很困惑,因爲在大多數語言中,我使用的參數列表與名稱的方法簽名一樣多。 – BigOmega

+2

那麼,Out of Box ASP.NET MVC如何處理每個請求的操作。最後,它歸結爲尋找具有與您正在調用的操作相匹配的別名的方法,並且與該方法關聯的所有屬性都返回true。它實際上並沒有將每種方法的參數作爲確定選擇哪種動作的手段。因此,當多個方法具有相同的別名並且所有屬性在所有這些方法都返回true時,框架不知道要調用哪個方法。您可以通過查看MVC源代碼中的ControllerActionInvoker.cs類來深入挖掘。 –

-1

這將是更好,如果你考慮使用創建和編輯的操作,以達到你想要的東西。通常索引可以用來列出所有的用戶(在你的情況)。 關於你面臨的問題,它出現了,因爲沒有任何路線沒有將任何id作爲參數。

+0

不能這樣做,我正在使用必要的冪等RESTful API URL,GET/PUT/DELETE將全部使用相同的/ users/[id] URL並且POST將使用/ users /(沒有ID),實際上現在我也使用POST進行創建,但現在你明白了。此外,這可能是比回答更好的評論,因爲它不回答問題。 – BigOmega

0

您必須通過擁有兩個不同的操作名稱來消除歧義。

如何讓RESTful API創建您自己的RouteHandler類,根據{id}值是否存在來改變路由。該RouteHandler類很簡單:

using System.Web.Mvc; 
using System.Web.Routing; 

    public class MyRouteHandler : IRouteHandler 
    { 
    public IHttpHandler GetHttpHandler(RequestContext requestContext) 
    { 
     var routeData = requestContext.RouteData; 
     if (routeData.Values("id").ToString() == "0" /* our default invalid value */) 
     { 
     var action = routeData.Values("action"); 
     routeData.Values("action") = action + "Add"; 
     } 
     var handler = new MvcHandler(requestContext); 
     return handler; 
    } 
    } 

接下來,修改RegisterRoutes()中的Global.asax.cs如下:

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

     AreaRegistration.RegisterAllAreas(); 

     routes.Add("Default", new Route("{controller}/{action}/{id}", 
      new RouteValueDictionary(
       new { controller = "Home", 
         action = "Index", 
         id = "0" /* our default invalid value */ }), 
      new MyRouteHandler())); 
    } 

最後,改變ActionName屬性爲您Add方法 「IndexAdd」。當請求沒有一個id時,會提供默認的無效值,這會提醒您的RouteHandler將方法更改爲您的「添加」方法。

counsellorben

相關問題