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 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?
While ASP.NET MVC will allow you to have two actions with the same name, . NET won't allow you to have two methods with the same signature - i.e. the same name and parameters. You will need to name the methods differently use the ActionName attribute to tell ASP.NET MVC that they're actually the same action.
Yes. Mention the view full path in the View method. If the name of your Views are same in both the controllers, You can keep the Common view under the Views/Shared directory and simply call the View method without any parameter. The View name should be same as the Action method name.
Yes, it's possible. Just make sure your views have same view model. From a technical stand point, views don't have to have the same view model implemented within the same action. There's just as long as the controller passes in the expected type.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With