为什么Asp.net MVC在具有不同参数时不能区分两个动作?

时间:2011-06-25 18:11:08

标签: c# .net asp.net asp.net-mvc routing

我正在尝试在我的Asp.net MVC应用程序中使用两种不同的帐户注册方法,一种用于一般用户注册,另一种用于注册特定注册令牌的用户。因此,我在AccountController中有以下方法签名:

public virtual ActionResult Register () {...}

public virtual ActionResult Register (Guid registrationToken) {...}

然而,当我转到http://localhost/Account/Register时,我得到一个例外,即当前请求在这两个动作之间是不明确的。我的印象是,如果没有传入Register GET参数,它将使用无参数registrationToken操作,否则它将使用第二个。

这是否需要特殊的路由配置?

3 个答案:

答案 0 :(得分:14)

使用可为空的参数设置一个方法会更容易吗?这也将自动解决您的问题,因为它不再模棱两可:

public virtual ActionResult Register (Guid? registrationToken)
{
    if(registrationToken.HasValue)
    {
         // this is specific user
    }         
    else
    {
         // this is general user
    }
}

答案 1 :(得分:11)

mvc控制器的默认基类,Controller使用ActionInvoker来选择要调用的操作。首先,操作选择,默认情况下从RouteData [“action”]值开始,然后发生所选操作参数的所有模型绑定和验证。这就是为什么当调用者看到两个具有相同名称和相同属性的动作进行选择时,它会触发错误,因为它无法区分两者。

但是有内置的方法来管理动作选择逻辑,即使用从ActionMethodSelector class派生的属性。首先,创建从中派生的类,其中包含用于调用操作的逻辑。在你的情况下

  

它将使用无参数   如果没有,请注册操作   registrationToken GET参数已传递   在,否则它将使用第二。

 public class RegistrationActionTokenAttribute : ActionMethodSelectorAttribute
    {
        public override bool IsValidForRequest(ControllerContext controllerContext, System.Reflection.MethodInfo methodInfo)
        {
            if (controllerContext.HttpContext.Request.QueryString.AllKeys.Contains("registrationToken"))
            {
                return true;
            }
            return false;
        }
    }

我实现了演示逻辑,如果querystring包含参数“registrationToken”,则第二个操作应标记为有效以供选择。剩下的东西就是用这个属性装饰你的第二个方法

[RegistrationActionToken]    
public virtual ActionResult Register (Guid registrationToken) {...}

错误消失了。此外,控制器现在根据查询字符串参数

选择正确的操作

答案 2 :(得分:3)

第二种方法是否需要发布?将[HttpPost]添加到用于接受表单提交的任何方法之上通常是有益的。

它也可以解决你的问题。