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

Kal*_*exx 14 .net c# asp.net asp.net-mvc routing

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

public virtual ActionResult Register () {...}

public virtual ActionResult Register (Guid registrationToken) {...}
Run Code Online (Sandbox Code Playgroud)

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

这需要特殊的路由配置吗?

Ale*_*Aza 14

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

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

  • @KallDrexx - 问题是,它没有区分'无参数'和'参数为空'.除了它不会区分'参数`a`被设置和参数`b`为空'和'参数'a`被设置并且没有参数'b`'.虽然对于简单的情况看起来似乎很明显,但对于棘手的情况来说这并不容易实现.这将是非常复杂且容易出错的决策框架. (2认同)

arc*_*hil 11

mvc控制器的默认基类,Controller使用ActionInvoker选择要调用的操作.第一动作被选择,通过默认从的RouteData ["行动"]的值,然后所有的模型绑定和验证为发生所选择的动作的参数.这就是为什么当调用者看到两个具有相同名称和相同属性的动作进行选择时,它会触发错误,因为它无法区分两者.

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

如果没有传入registrationToken GET参数,它将使用无参数的Register操作,否则它将使用2nd.

 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;
        }
    }
Run Code Online (Sandbox Code Playgroud)

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

[RegistrationActionToken]    
public virtual ActionResult Register (Guid registrationToken) {...}
Run Code Online (Sandbox Code Playgroud)

错误消失了.此外,控制器现在根据查询字符串参数选择正确的操作