Why can't Asp.net MVC distinguish between two actions when they have different parameters?
I am trying to have two different methods for account registration in my Asp.net MVC application, one for general users to register for and another for users who are registering with a specific registration token. Thus I have the following method signatures in my AccountController
:
public virtual ActionResult Register () {...}
public virtual ActionResult Register (Guid registrationToken) {...}
However, when I开发者_JAVA技巧 go to http://localhost/Account/Register
I get an exception that the current request is ambiguous between these two actions. I was under the impression that it would use the parameterless Register
action if there was no registrationToken
GET parameter passed in, otherwise it would use the 2nd.
Does this require special route configuration?
Would it be easier to have one method with a nullable parameter? This will also automatically solve your problem as it will not be ambiguous anymore:
public virtual ActionResult Register (Guid? registrationToken)
{
if(registrationToken.HasValue)
{
// this is specific user
}
else
{
// this is general user
}
}
Default base class for mvc controllers, Controller
uses ActionInvoker to select which action to invoke. First the action is selected, by default from the RouteData["action"] value, and then all the model binding and validation for the selected action's parameters occur. That's why when the invoker sees two actions with the same name and same attributes for selecting, it fires error, as it cannot distinguish between two.
But there's builtin way to manage action selecting logic, that is by using attributes derived from ActionMethodSelector class. First you create class derived from it, which contains logic for invoking action. In your case
it would use the parameterless Register action if there was no registrationToken GET parameter passed in, otherwise it would use the 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;
}
}
I implemented demonstrational logic that second action should be marked valid for selection, if querystring contains parameter "registrationToken". The ony thing left is to decorate your second method with this attribute
[RegistrationActionToken]
public virtual ActionResult Register (Guid registrationToken) {...}
And the error is gone. Moreover, controller now selects correct action, depending on query string parameter
Does the 2nd method require Post? It's usually beneficial to add [HttpPost] above any method that will be used to accept a form submission.
And it may also solve your problem.
精彩评论