路由:当前的操作请求 [...] 在以下操作方法之间不明确
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 完成这项工作。
【讨论】:
以上是关于路由:当前的操作请求 [...] 在以下操作方法之间不明确的主要内容,如果未能解决你的问题,请参考以下文章