Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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 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?

like image 453
KallDrexx Avatar asked Jun 25 '11 18:06

KallDrexx


People also ask

Can we have two action methods with same name in MVC?

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.

Can two different controllers access a single view in MVC?

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.

Can one action method have multiple views?

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.


2 Answers

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
    }
}
like image 55
Alex Aza Avatar answered Oct 15 '22 00:10

Alex Aza


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

like image 35
archil Avatar answered Oct 15 '22 00:10

archil