Вопрос по asp.net-mvc, c# – ASP.NET MVC: вернуть Redirect и ViewData

10

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

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

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

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

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

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

Спасибо

Ваш Ответ

5   ответов
16

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

Помните, что TempData использует состояние сеанса - со всеми последствиями.
+1 Только то, что я думал. В MvcContrib также имеется набор удобных фильтров действий, которые копируют ModelState в TempState и из него, так что у вас есть информация проверки после перенаправления. Смотрите пункт 13 в этой статье для примераweblogs.asp.net/rashid/archive/2009/04/01/…
2

можете легко указать статус, 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;
      });
  });
Привет, я знаю, что могу справиться с этим через ajax, и это то, что я собираюсь сделать, но я хотел бы знать, как решить проблему, как есть, поскольку могут быть случаи, когда использование простого POST более уместно, или даже просто требуется клиентом. pistacchio
Вы можете иметь представление, которое должно отображаться при ошибке, в качестве скрытого параметра отправляемой формы. К сожалению, вам, вероятно, также необходимо сериализовать любые данные модели, содержащиеся в этом представлении, для передачи вместе с запросом на вход в систему, поскольку в противном случае невозможно сохранить его между запросами. Делать это с AJAX будет намного чище. Обратите внимание, что приведенный выше код будет перенаправлять на страницу входа (однако, не в исходное представление), если javascript недоступен. Вот как я бы это обработал - перетащите ошибку на страницу входа в систему и дайте пользователю повторить аутентификацию оттуда.
1

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

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

ModelState.AddModelError(...);

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

В то время как использование AJAX для входа (как предложено tvanfosson) вполне достижимо и иногда превосходно в пользовательском опыте, классический полный пост все еще не заменяется (учтите, что некоторые пользователи отключают JavaScript или даже на моей телефонной трубке WM6, которая не поддерживает JavaScript) ).

Согласитесь использовать как форму сообщения AJAX +, если нет JS, так и для моих проектов, я бы также использовал оба. Но проблема с фисташками все еще сохраняется.
Хотя мой пример кода не завершен, я думаю, что его структура будет справляться со случаем, когда javascript недоступен. В этом случае форма входа будет заполнена, а любые ошибки будут перенаправлены обратно на страницу входа, как вы описали.
1

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. Таким образом, подход r, ight - вернуть тот же View () и использовать ModelState для ошибок, как упомянуто в «xandy». также.

Надеюсь, это даст вам преимущество при проверке формы.

1

Я в замешательстве. Doesn & APOS; т

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();
}

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

View () возвращает представление по умолчанию для действия, которое может быть или не быть текущим представлением. Если вы используете представления с моделями, он также не включает модель, используемую текущим представлением, или любые другие параметры.

Похожие вопросы