ASP.NET MVC: вернуть Redirect и ViewData

У меня есть окно входа в мой MasterPage. Всякий раз, когда данные входа неверны, я оцениваю ViewData["loginError"], чтобы показать сообщение об ошибке пользователю.

Вход - это действие UserController, поэтому форма, содержащая логин, имеет action = "/User/Login".

Как пользователь может попытаться войти в систему с любой страницы, в случае успеха я перенаправляю его на личную страницу, но в случае ошибки я хочу, чтобы он остался на той же странице, где он пытался войти. Я обнаружил, что это работает:

return Redirect(Request.UrlReferrer.ToString());

но кажется, что, поскольку я не возвращаю надлежащее представление, данные в ViewData теряются, поэтому я не могу показать сообщение об ошибке.

Любое предложение о том, как решить эту и подобные проблемы?

Спасибо

Ответ 1

Вероятно, вы хотите использовать свойство TempData, это будет сохраняться до следующего HTTP-запроса.

Ответ 2

Почему бы не обработать логин через AJAX вместо полного сообщения? Вы можете легко предоставить статус, URL-адрес перенаправления и любые сообщения об ошибках через JSON.

public ActionResult Logon( string username, string password )
{
     ...

     // Handle master page login
     if (Request.IsAjaxRequest())
     {
          if (success)
          {
              return Json( new { Status = true, Url = Url.Action( "Index", "Home" ) } );
          }
          else
          {
              return Json( new { Status = false, Message = ... } );
          }
     }
     else // handle login page logon or no javascript
     {
          if (success)
          {
              return RedirectToAction( "Index", "Home" );
          }
          else
          {
              ViewData["error"] = ...
              return View("Logon");
          }
      }
  }

Клиентская сторона

  $(function() {
      $('#loginForm input[type=submit]').click( function() {
          $('#loginError').html('');
          $.ajax({
             url: '<%= Url.Action("Logon","Account") %>',
             dataType: 'json',
             type: 'post',
             data: function() { return $('#loginForm').serialize(); },
             success: function(data,status) {
                 if (data.Status) {
                     location.href = data.Url;
                 }
                 else {
                     $('#loginError').html( data.Message );
                 }
             }
          });
          return false;
      });
  });

Ответ 3

Обычно для большинства веб-сайтов, когда пользователь не может пройти аутентификацию (из-за пароля или так), он перейдет на другую страницу, которая поможет пользователю (например, восстановить пароль или попросить пользователя зарегистрироваться), что редко встречается Оставайтесь на той же странице. Я думаю, вы можете подумать, что вам действительно нужна навигационная система, которую вы используете.

ОК, одно решение, если вы действительно хотите придерживаться своей модели, заключается в том, что вы можете прикрепить ошибку входа в URL. Например, http://www.example.com/index.aspx?login_error=1 указывает на эту ошибку, и вы можете использовать BEGIN_REQUEST (или HTTP-модуль), чтобы зафиксировать это, и сообщить состояние модели об ошибке:

ModelState.AddModelError(...);

BTW, добавление ошибки модели на самом деле является более правильным способом информировать представление о любой ошибке, а не использовать ViewState (это похоже на исключение throw и исключение целого числа результата выполнения в старые времена).

При использовании AJAX для входа в систему (как предложено tvanfosson) вполне достижимо и иногда превосходит пользовательский интерфейс, классическая полноценная запись все еще невосприимчива (подумайте, что какой-то пользователь отключит javascript или даже на моей дампе WM6-телефоне, t поддержка javascript).

Ответ 4

Я в замешательстве. Не

return View();

просто верните текущую страницу назад?

Итак, в вашем случае, когда логин завершается с ошибкой, установите ваши viewdata и вызовите return View();

то есть.

if (!FailedLogin) {
  //Go to success page
}else{
  //Add error to View Data or use ModelState to add error
  return View();
}

Используете ли вы [Authorize] декоратор? Автоматическая процедура входа в систему MVC запрашивает страницу входа в систему, а затем возвращает вас к действию контроллера, которое вы пытались выполнить. Сокращает много перенаправлений.

Ответ 5

Следующий пример, надеюсь, поможет вам решить эту проблему:

View.aspx

<%= Html.ValidationSummary("Login was unsuccessful. Please correct the errors and try again.") %>
<% using (Html.BeginForm()) { %>
    <div>
        <fieldset>
            <legend>Account Information</legend>
            <p>
                <label for="username">Username:</label>
                <%= Html.TextBox("username") %>
                <%= Html.ValidationMessage("username") %>
            </p>
            <p>
                <label for="password">Password:</label>
                <%= Html.Password("password") %>
                <%= Html.ValidationMessage("password") %>
            </p>
            <p>
                <%= Html.CheckBox("rememberMe") %> <label class="inline" for="rememberMe">Remember me?</label>
            </p>
            <p>
                <input type="submit" value="Log On" />
            </p>
        </fieldset>
    </div>
<% } %>

AccountController.cs

private bool ValidateLogOn(string userName, string password)
{
    if (String.IsNullOrEmpty(userName))
    {
        ModelState.AddModelError("username", "You must specify a username.");
    }
    if (String.IsNullOrEmpty(password))
    {
        ModelState.AddModelError("password", "You must specify a password.");
    }
    if (!MembershipService.ValidateUser(userName, password))
    {
        ModelState.AddModelError("_FORM", "The username or password provided is incorrect.");
    }
    return ModelState.IsValid;
}

Вы не сможете захватить информацию, добавленную в ViewData после действия Redirect. поэтому правильный подход заключается в том, чтобы вернуть тот же View() и использовать ModelState для ошибок, как упоминалось также "xandy".

Надеюсь, что это дало бы начало с проверкой формы.