【问题标题】: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

【问题讨论】:

    标签: asp.net-mvc routing


    【解决方案1】:

    我会有一个查找有效类型变量的 Index 方法

        public class IssueController : Controller  
    {  
        public ActionResult Index(string type)  
        {  
            if(string.isNullOrEmpty(type)){
                return View("viewWithOutType");}
            else{
                return View("viewWithType");} 
        }
    }
    

    编辑:

    如何创建一个自定义属性来查找特定请求值,如本文StackOverflow 中所述

    [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] 标签,不确定哪个(如果有)框架版本需要这个标签,但是标记两者更容易推理。
    猜你喜欢
    • 1970-01-01
    • 2016-01-22
    • 2018-09-19
    • 2019-07-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-23
    相关资源
    最近更新 更多