路由到同名但参数不同的动作
Posted
技术标签:
【中文标题】路由到同名但参数不同的动作【英文标题】:Routing to the actions with same names but different parameters 【发布时间】:2011-02-07 05:52:01 【问题描述】:我有这组路线:
routes.MapRoute(
"IssueType",
"issue/type",
new controller = "Issue", action = "Index"
);
routes.MapRoute(
"Default", // Route name
"controller/action/id", // URL with parameters
new controller = "Home", action = "Index", id = UrlParameter.Optional // Parameter defaults
);
这是控制器类:
public class IssueController : Controller
public ActionResult Index()
// todo: redirect to concrete type
return View();
public ActionResult Index(string type)
return View();
为什么,当我请求http://host/issue 我得到The current request for action 'Index' on controller type 'IssueController' is ambiguous between the following action methods:
我希望第一个方法应该在没有参数时起作用,而第二个方法应该在指定参数时起作用。
我哪里做错了?
UPD:可能重复:Can you overload controller methods in ASP.NET MVC?
UPD 2:由于上面的链接 - 没有任何合法的方法可以使动作重载,是吗?
UPD 3:动作方法不能基于参数重载(c)http://msdn.microsoft.com/en-us/library/system.web.mvc.controller%28VS.100%29.aspx
【问题讨论】:
【参考方案1】:我会有一个查找有效类型变量的 Index 方法
public class IssueController : Controller
public ActionResult Index(string type)
if(string.isNullOrEmpty(type))
return View("viewWithOutType");
else
return View("viewWithType");
编辑:
如何创建一个自定义属性来查找特定请求值,如本文*** 中所述
[RequireRequestValue("someInt")]
public ActionResult MyMethod(int someInt) /* ... */
[RequireRequestValue("someString")]
public ActionResult MyMethod(string someString) /* ... */
public class RequireRequestValueAttribute : ActionMethodSelectorAttribute
public RequireRequestValueAttribute(string valueName)
ValueName = valueName;
public override bool IsValidForRequest(ControllerContext controllerContext, MethodInfo methodInfo)
return (controllerContext.HttpContext.Request[ValueName] != null);
public string ValueName get; private set;
【讨论】:
是的,这很明显,但实际上并不是解决问题的方法 是的,这会带来某种重载但太脏,所以我选择简单地重命名第二种方法。谢谢【参考方案2】:我遇到了类似的情况,如果我指定了 ID,我希望我的“索引”操作来处理渲染。我遇到的解决方案是使 Index 方法的 ID 参数可选。 例如,我最初尝试同时拥有两者:
public ViewResult Index()
//...
// AND
public ViewResult Index(int entryId)
//...
我只是将它们合并并更改为:
public ViewResult Index(int entryId = 0)
//...
【讨论】:
这可能是 .NET 4.0 的解决方案,但我当时使用的是 3.5 ;-)【参考方案3】:您可以使用使用反射检查参数的 ActionFilterAttribute 来做到这一点(我试过了),但这是个坏主意。 每个不同的动作都应该有自己的名字。
为什么不直接称你的两个方法为“Index”和“Single”,并忍受命名的限制?
与在编译时基于匹配签名绑定的方法不同,最后缺少的路由值被视为空值。
如果您想要匹配参数的 [hack] ActionFilterAttribute,请告诉我,我会发布一个链接,但就像我说的那样,这是个坏主意。
【讨论】:
我已经重命名了第二个,所以我有两种方法。实际上,我得到了很多指向 ActionFilterAttribute 的链接 - 这是一个更糟糕的解决方案。还是谢谢你。【参考方案4】:您所要做的就是用 [HttpPost] 标记您的第二个操作。例如:
public class IssueController : Controller
public ActionResult Index()
// todo: redirect to concrete type
return View();
[HttpPost]
public ActionResult Index(string type)
return View();
【讨论】:
谁告诉你第二个已经发布了? 我经常看到这种情况,尤其是对于登录方法 - 一个 Get 操作提供初始视图,而 Post 接受登录请求并重定向。一般来说,我在第一个标签上也看到了[HttpGet]
标签,不确定哪个(如果有)框架版本需要这个标签,但是标记两者更容易推理。以上是关于路由到同名但参数不同的动作的主要内容,如果未能解决你的问题,请参考以下文章