ASP.NET MVC - Как поддерживать ModelState с другого контроллера? - PullRequest
10 голосов
/ 23 декабря 2010

У меня есть HomeController с действием Index, которое отображает представление Index.aspx.Он имеет раздел логин / пароль для входа.Когда пользователь нажимает кнопку отправки, он выполняет POST-действие для входа в систему в AccountController.

        <% Html.BeginForm("Login", "Account", FormMethod.Post); %>

В этом действии он проверяет правильность имени пользователя / пароля и, если он неверен, отправляет пользователя обратно на страницу входас сообщением о том, что учетные данные были неверными.

    [HttpPost]
    public ActionResult Login(LoginViewModel Model, string ReturnUrl)
    {
        User user = MembershipService.ValidateUser(Model.UserName, Model.Password);
        if (user != null)
        {
            //Detail removed here
            FormsService.SignIn(user.ToString(), Model.RememberMe);
            return Redirect(ReturnUrl);
        }
        else
        {
            ModelState.AddModelError("", "The user name or password provided is incorrect.");
        }
        // If we got this far, something failed, redisplay form
        return RedirectToAction("Index", "Home");  // <-- Here is the problem.  ModelState is lost.
    }

Но вот проблема: ValidationSummary всегда пуст, потому что мы теряем Модель, когда мы RedirectToAction. Как отправить пользователя на действие на другом контроллере без перенаправления?

Ответы [ 5 ]

7 голосов
/ 24 декабря 2010

Используйте TempData для сохранения состояния между запросами.Для удобства используйте специальные атрибуты, как показано здесь .

Несколько моментов для упоминания:

  • Не возвращайте View напрямую из вашего POST-действия, уважайте Post-Redirect-Get pattern.
  • Не злоупотребляйте TempData. только должен сохранять состояние модели непосредственно перед перенаправлением и извлекать его сразу после перенаправления.
7 голосов
/ 24 декабря 2010

Как уже говорили другие, возвращать представление, если проверка не пройдена, обычно, но когда вы звоните с контроллера своей учетной записи, вам нужно будет указать полный путь к вашему просмотру

return View("~/Views/Home/Index.aspx", model);

или

Также обычно есть отдельная страница входа и перенаправление на эту страницу в случае сбоя входа.На обеих страницах будет выполнено одно и то же действие при входе.Например, Facebook делает это.

Или

Поскольку вы хотите отобразить только сообщение об ошибке

return RedirectToAction("Index", "Home", new { LoginAttempts = 1 });

, в своем действии Index прочитайте параметр LoginAttempts и выберитедля отображения сообщения об ошибке соответственно.

2 голосов
/ 23 декабря 2010

Ну, вы всегда можете сделать это

return View("~/Views/Home/Index.aspx", myModel);

Это не настоящий редирект, URL-адрес клиента все равно будет указывать на / login /, но, по крайней мере, у вас есть ваш modalstate

2 голосов
/ 23 декабря 2010

Три варианта

  1. Вы можете вызвать действие напрямую, но на стороне клиента не будет изменен его URL. Поэтому вместо вызова RedirectToAction вы можете вызвать метод Index() класса HomeController напрямую.

    HomeController c = new HomeController();
    c.ViewData = this.ViewData;
    return c.Index(data);
    

    Один немного хитрый. Возможно, вам придется установить и другие вещи, кроме ViewData, который необходим для ModelState.

  2. Вы можете также использовать словарь TempData и заполнить его любыми данными, которые вы хотите, и использовать их.

  3. Самый простой, где вы указываете полный путь к представлению

    return View("~/Views/Home/Index.aspx", data);
    

Лучшее предложение, используемое крупными игроками

Если мы посмотрим, как другие сайты делают такой сценарий. Возьмем, к примеру, Twitter (как говорит @David Facebook , очевидно, делает то же самое). Вы можете войти с помощью действия Home/Index (так сказать, если оно было разработано с использованием Asp.net MVC). Но при неудачном входе в систему отображается отдельная страница входа, на которой отображаются ошибки проверки. В вашем случае это будет Account/SignIn. Что имело бы смысл, и вы могли бы напрямую вернуть его представление с ошибками проверки. Когда все будет хорошо, ты сделаешь это так, как сейчас. Перенаправить обратно на Home/Index.

0 голосов
/ 24 декабря 2010

Попробуйте использовать

return View("Index", "Home", Model)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...