Почему Asp.net MVC не может различать два действия, когда они имеют разные параметры?
Я пытаюсь иметь два разных метода для регистрации учетной записи в моем приложении MVC Asp.net, один для обычных пользователей для регистрации, а другой для пользователей, которые регистрируются с определенным регистрационным токеном. Таким образом, у меня есть следующие сигнатуры методов в моем AccountController
:
public virtual ActionResult Register () {...}
public virtual ActionResult Register (Guid registrationToken) {...}
Однако, когда я перехожу к http://localhost/Account/Register
, я получаю исключение, что текущий запрос неоднозначен между этими двумя действиями. У меня создалось впечатление, что он использовал бы безпараметрическое действие Register
, если бы не был передан параметр registrationToken
GET, иначе он будет использовать второй.
Требуется ли для этого специальная настройка маршрута?
Ответы
Ответ 1
Было бы проще иметь один метод с параметром nullable? Это также автоматически решит вашу проблему, поскольку она не будет неоднозначной:
public virtual ActionResult Register (Guid? registrationToken)
{
if(registrationToken.HasValue)
{
// this is specific user
}
else
{
// this is general user
}
}
Ответ 2
Стандартный базовый класс для контроллеров mvc, Controller
использует ActionInvoker, чтобы выбрать действие для вызова. Сначала действие выбрано, по умолчанию из значения RouteData [ "action" ], а затем все привязки и проверки модели для выбранных параметров действия происходят. Поэтому, когда invoker видит два действия с тем же именем и одинаковыми атрибутами для выбора, он запускает ошибку, так как не может различать два.
Но существует встроенный способ управления логикой выбора действий, то есть с использованием атрибутов, полученных из класса ActionMethodSelector. Сначала вы создаете из него класс, содержащий логику для вызова действия. В вашем случае
он будет использовать без параметров Зарегистрировать действие, если не было 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) {...}
И ошибка исчезла. Кроме того, теперь контроллер выбирает правильное действие, в зависимости от параметра строки запроса
Ответ 3
Требуется ли второй метод Post? Обычно полезно добавить [HttpPost] выше любого метода, который будет использоваться для приема отправки формы.
И это также может решить вашу проблему.