路由:当前的操作请求 [...] 在以下操作方法之间不明确

Posted

技术标签:

【中文标题】路由:当前的操作请求 [...] 在以下操作方法之间不明确【英文标题】:Routing: The current request for action [...] is ambiguous between the following action methods 【发布时间】:2012-05-26 22:35:43 【问题描述】:

我有一个名为Browse.chtml 的视图,用户可以在其中输入搜索词,或将搜索词留空。输入搜索词时,我想将页面定向到http://localhost:62019/Gallery/Browse/Searchterm,当没有输入时,我想将浏览器定向到http://localhost:62019/Gallery/Browse/Start/Here

当我尝试这个时,我得到了错误:

当前对控制器类型“GalleryController”的“浏览”操作请求在以下操作方法之间不明确: System.Web.Mvc.ActionResult Browse(System.String) 类型为 AutoApp_MVC.Controllers.GalleryController System.Web.Mvc.ActionResult Browse(Int32, System.String) on type AutoApp_MVC.Controllers.GalleryController

我对 MVC 所做的一切都是第一次。我不确定目前还可以尝试什么。

public ActionResult Browse(string id)

    var summaries = /* search using id as search term */
    return View(summaries);


public ActionResult Browse(string name1, string name2)

    var summaries = /* default list when nothing entered */
    return View(summaries);

我在 Global.asax.cs 中也有这个:

    routes.MapRoute(
         "StartBrowse",
         "Gallery/Browse/s1/s2",
         new
         
             controller = "Gallery",
             action = "Browse",
             s1 = UrlParameter.Optional,
             s2 = UrlParameter.Optional
         );



    routes.MapRoute(
         "ActualBrowse",
         "Gallery/Browse/searchterm",
         new
         
             controller = "Gallery",
             action = "Browse",
             searchterm=UrlParameter.Optional
         );

【问题讨论】:

【参考方案1】:

一个控制器上最多只能有 2 个同名的操作方法,为此,1 个必须是 [HttpPost],另一个必须是 [HttpGet]

由于您的两个方法都是 GET,您应该重命名其中一个操作方法或将其移动到不同的控制器。

尽管您的 2 Browse 方法是有效的 C# 重载,但 MVC 操作方法选择器无法确定调用哪个方法。它将尝试将路由匹配到方法(反之亦然),并且此算法不是强类型的。

您可以使用指向不同操作方法的自定义路由来完成您想要的:

...在 Global.asax 中

routes.MapRoute( // this route must be declared first, before the one below it
     "StartBrowse",
     "Gallery/Browse/Start/Here",
     new
     
         controller = "Gallery",
         action = "StartBrowse",
     );

routes.MapRoute(
     "ActualBrowse",
     "Gallery/Browse/searchterm",
     new
     
         controller = "Gallery",
         action = "Browse",
         searchterm = UrlParameter.Optional
     );

...在控制器中...

public ActionResult Browse(string id)

    var summaries = /* search using id as search term */
    return View(summaries);


public ActionResult StartBrowse()

    var summaries = /* default list when nothing entered */
    return View(summaries);

您还可以通过将[ActionName] 属性应用于一个来区分它,从而keep the action methods named the same in the controller。使用与上面相同的 Global.asax,您的控制器将如下所示:

public ActionResult Browse(string id)

    var summaries = /* search using id as search term */
    return View(summaries);


[ActionName("StartBrowse")]
public ActionResult Browse()

    var summaries = /* default list when nothing entered */
    return View(summaries);

【讨论】:

那么,我需要在上面的示例中创建一个新视图吗?看起来使用 ActionName 标记没有帮助,因为我认为这只适用于重命名所有操作方法(无法同时保留两者)。很高兴知道 MVC 是如何工作的。谢谢。 不,您不需要创建任何新视图。您仍然可以为这两个操作重复使用相同的视图。只需将视图名称作为第一个参数传递给return View("Browse", summaries); 未来的版本中会包含重载吗?修改路线是一项额外的工作,并且在进行更改时需要额外的维护。 @OldGeezer 可能不是,因为有一种解决方法(如上),并且控制器中的重载操作方法通常不是一个好主意。【参考方案2】:

我不知道什么时候问这个问题,这个解决方案是可用的,但你可以使用:

Request.QueryString["key"]

所以这应该可以很好地解决您的问题:

[HttpGet]
public ActionResult Browse()

    if( Request.QueryString["id"] != null )        
        var summaries = /* search using id as search term */
    else /*assuming you don't have any more option*/
        var summaries = /* default list when nothing entered */

    return View(summaries);
 

【讨论】:

【参考方案3】:

默认路由之前在RouteConfig.cs中添加以下代码

routes.MapMvcAttributeRoutes();

并在控制器中添加路由属性,如:

    [Route("Cars/deteals/id:int")]
    public ContentResult deteals(int id)
    
        return Content("<b>Cars ID Is " + id + "</b>");
    

    [Route("Cars/deteals/name")]
    public  ContentResult deteals(string name)
    
        return Content("<b>Car name Is " + name + "</b>");

    

【讨论】:

【参考方案4】:

我认为重点是您不需要使用请求类隐式测试查询字符串参数。

MVC 为您进行映射(除非您对 MVC 路由进行了重大更改)。

因此是一个actionlink路径

/umbraco/Surface/LoginSurface/Logout?DestinationUrl=/home/

将自动提供给您的(表面)控制器并定义参数:

public ActionResult Logout(string DestinationUrl)

MVC 完成这项工作。

【讨论】:

以上是关于路由:当前的操作请求 [...] 在以下操作方法之间不明确的主要内容,如果未能解决你的问题,请参考以下文章

node.js之路由,中间件,ge请求和post请求的参数

vue路由跳转取消上个页面的异步请求

SpringCloud学习系列之七 ----- Zuul路由网关的过滤器和异常处理

React中路由操作、页面跳转

ASP.NET Core 中的模型绑定

Django框架之路由