asp.net-mvc - method - redirecttoaction post
ASP.NET MVC: ¿cómo mantener ModelState desde un controlador diferente? (5)
Tengo un HomeController con una acción de índice que muestra la vista de Index.aspx. Tiene una sección de inicio de sesión de nombre de usuario / contraseña. Cuando el usuario hace clic en el botón de enviar, envía a una acción de inicio de sesión en AccountController.
<% Html.BeginForm("Login", "Account", FormMethod.Post); %>
En esa acción, prueba la validez de nombre de usuario / contraseña y, si no es válida, envía al usuario a la página de inicio de sesión con un mensaje de que las credenciales eran incorrectas.
[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.
}
Pero aquí está el problema: el ValidationSummary siempre está en blanco porque estamos perdiendo el Modelo cuando RedirectToAction.
Entonces, la pregunta es: ¿cómo puedo enviar al usuario a la acción en un controlador diferente sin una redirección?
Bueno, siempre puedes hacer esto
return View("~/Views/Home/Index.aspx", myModel);
No es una redirección real, la URL de los clientes aún señalará / login / pero al menos tiene su modalstate
Como otros han dicho, es común devolver la vista si la validación falla, pero como está llamando desde su controlador de cuenta, querrá especificar la ruta completa de su vista.
return View("~/Views/Home/Index.aspx", model);
O
También es común tener una página de inicio de sesión separada y redirigir a esa página si falla el inicio de sesión. Ambas páginas se enviarán a la misma acción de inicio de sesión. Facebook hace esto, por ejemplo.
O
Como solo quieres mostrar un mensaje de error
return RedirectToAction("Index", "Home", new { LoginAttempts = 1 });
luego, en su acción de índice, lea el parámetro LoginAttempts
y elija mostrar el mensaje de error en consecuencia.
Intenta usar
return View("Index", "Home", Model)
Use TempData
para guardar el estado entre las solicitudes. Use atributos especiales por conveniencia como se muestra aquí .
Pocos momentos para mencionar:
- No devuelva View directamente de su POST-action, respete el patrón Post-Redirect-Get .
- No
TempData
demasiadoTempData
. Se supone que solo debe guardar el estado del modelo justo antes de redirigir y recuperarlo justo después de ser redirigido.
Tres opciones
Puede llamar a la acción directamente, pero el lado del cliente no cambiará su URL. Entonces, en lugar de llamar a
RedirectToAction
, puede llamar directamente al métodoIndex()
de la claseHomeController
.HomeController c = new HomeController(); c.ViewData = this.ViewData; return c.Index(data);
El es un poco complicado. Tal vez tendrá que establecer otras cosas además de
ViewData
que se necesita paraModelState
.También podría usar el diccionario
TempData
y llenarlo con los datos que desee y usarlos.El más simple en el que proporciona un camino completo a la vista
return View("~/Views/Home/Index.aspx", data);
Una mejor sugerencia utilizada por los grandes jugadores
Si miramos cómo otros sitios hacen este tipo de escenario. Tomemos por ejemplo Twitter (como dice @David que Facebook aparentemente lo hace de la misma manera). Puede iniciar sesión desde la acción Home/Index
(por así decirlo, si se desarrolló utilizando Asp.net MVC). Pero cuando falla el inicio de sesión, muestra una página de inicio de sesión separada, que muestra los errores de validación. En su caso, sería Account/SignIn
. Lo cual tendría sentido y podría devolver su vista directamente con errores de validación. Cuando todo estaría bien, lo harías como lo haces ahora. Redirigir a Home/Index
.