c# - net - ¿Cómo mantengo los errores de ModelState cuando uso RedirectToAction?
mvc c# (6)
Tengo un código que guarda un ticket en nuestro sistema. Si hay un error hace un RedirectToAction. El problema es que parece que no tengo mis errores en la nueva acción. ¿Cómo puedo arreglar esto?
ModelState.AddModelError("_FORM", "Unable to save ticket");
ModelState.AddModelError("_FORM", "Phone number was invalid.");
ModelState.AddModelError("_FORM", "Lane number is required.");
return RedirectToAction("CreateStep", "Ticket");
Sé que algunos han sugerido usar TempData, pero ¿cómo puedo eliminar cada error del ModelState?
Gracias.
Creo que pierdes tu estado modelo cuando haces una redirección. Tal vez podrías reescribir tu lógica a algo como:
public ActionResult Save()
{
// your code...
if(saveSucceeded)
{
return View("Saved");
}
else
{
return View("Create");
}
}
Y la forma habitual de obtener su mensaje de error:
<%= Html.ValidationMessage("property_name") %>
El patrón PRG está bien, pero hice esto:
Controlador base:
protected override void OnActionExecuted(ActionExecutedContext filterContext)
{
if (TempData["ModelState"] != null && !ModelState.Equals(TempData["ModelState"]))
ModelState.Merge((ModelStateDictionary)TempData["ModelState"]);
base.OnActionExecuted(filterContext);
}
Acción (estoy usando xVal ):
try
{
user.Login();
AuthenticationManager.SignIn(user);
}
catch (RulesException rex)
{
// on bad login
rex.AddModelStateErrors(ModelState, "user");
TempData["ModelState"] = ModelState;
return Redirect(Request.UrlReferrer.ToString());
}
La acción lanza una excepción, agrega el ModelState a TempData y vuelve a dirigir al remitente. Dado que la acción se captura, OnActionExecuted aún se ejecuta, pero la primera vez alrededor de ModelState es la misma que TempData ["ModelState"], por lo que no desea fusionarse con usted mismo. Cuando se ejecuta la acción de redireccionamiento, OnActionExecuted se activa de nuevo. Esta vez, si hay algo en TempData ["ModelState"], se fusiona con el ModelState de esta acción.
Puede expandirlo a varios modelos utilizando TempData ["ModelState.user"] = ModelState y luego fusionando cada objeto TempData que comienza con ModelState.
Lo que hice para mantener mi ModelState sin importar a dónde vaya con las redirecciones es lo siguiente:
En su modelo, agregue:
public ModelStateDictionary modelstate { get; set; }
En el constructor de tu modelo, agrega:
this.modelstate = new System.Web.Mvc.ModelStateDictionary();
Muestra de muestra con mi modelo llamada Models.ContactInformation:
[HttpPost] [ValidateAntiForgeryToken] public ActionResult contact(Models.ContactInformation con) { if (string.IsNullOrEmpty(con.SelectedAgencySelectorType)) { ModelState.AddModelError("", "You did not select an agency type."); } con.modelstate = ModelState; TempData["contact"] = con; if (!ModelState.IsValid) return RedirectToAction("contactinformation", "reports"); //do stuff return RedirectToAction("contactinformation", "reports"); }
Así que ahora tu tempdata tiene tu modelo y estado de modelo como es.
La siguiente es mi opinión que es agnóstica al estado de cualquier cosa, a menos que tenga algo. Aquí está el código:
[HttpGet] public ActionResult contactinformation() { //try cast to model var m = new Models.ContactInformation(); if (TempData["contact"] is Models.ContactInformation) m = (Models.ContactInformation)TempData["contact"]; //restore modelstate if needed if (!m.modelstate.IsValid) { foreach (ModelState item in m.modelstate.Values) { foreach (ModelError err in item.Errors) { ModelState.AddModelError("", err.ErrorMessage.ToString()); } } } return View(m); }
Sé que este hilo es antiguo, pero este blog sobre las mejores prácticas de ASP.NET tiene algunas sugerencias excelentes.
El # 13 en la página trata sobre el uso de 2 filtros de acción para guardar y restaurar ModelState
entre redirecciones.
Este es el patrón que utiliza mi trabajo, y me encanta.
Aquí está el ejemplo simplificado:
[ImportModelStateFromTempData]
public ActionResult Dashboard()
{
return View();
}
[AcceptVerbs(HttpVerbs.Post), ExportModelStateToTempData]
public ActionResult Dashboard(string data)
{
if (ValidateData(data))
{
try
{
_service.Submit(data);
}
catch (Exception e)
{
ModelState.AddModelError(ModelStateException, e);
}
}
return RedirectToAction("Dashboard");
}
Utilice la colección TempData []
El tempdata se almacena de una solicitud a la siguiente, luego desaparece.
esta publicación del blog describe cómo podría implementar el patrón PRG en MVC http://blog.simonlovely.com/archive/2008/11/26/post-redirect-get-pattern-in-mvc.aspx
hth