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


100

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

当我尝试此操作时,出现错误:

在以下操作方法之间,当前对控制器类型“ GalleryController”采取的“浏览”操作请求不明确:类型为AutoApp_MVC.Controllers.GalleryController的System.Web.Mvc.ActionResult Browse(System.String)System.Web.Mvc.ActionResult浏览(Int32,System.String)在类型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
         });

Answers:


161

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

由于两种方法都是GET,因此您应该重命名其中一种操作方法或将其移至其他控制器。

尽管您的2个浏览方法是有效的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]。使用与上述相同的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的工作原理。谢谢。
戴夫

6
不,您不需要创建任何新视图。您仍然可以对两个操作重复使用相同的视图。只需将视图名称作为第一个参数传递给return View("Browse", summaries);
danludwig 2012年

将来的某些发行版中会包含重载吗?修改路线是一项额外的工作,并且在进行更改时需要进行额外的维护。
老盖泽2015年

@OldGeezer可能不是,因为有一种解决方法(上述),并且因为控制器中重载的操作方法通常不是一个好主意。
danludwig 2015年

4

我不知道何时问这个解决方案可用,但是您可以使用:

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);
} 

2

默认路由之前在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>");

    }

1

我认为要指出的是,您不需要使用请求类隐式测试querystring参数。

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

因此,

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

使用定义的参数后,您的(表面)控制器将自动可用:

public ActionResult Logout(string DestinationUrl)

MVC可以完成工作。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.