Ich habe die folgenden zwei Aktionsmethoden (für Fragen vereinfacht):
[HttpGet]
public ActionResult Create(string uniqueUri)
{
// get some stuff based on uniqueuri, set in ViewData.
return View();
}
[HttpPost]
public ActionResult Create(Review review)
{
// validate review
if (validatedOk)
{
return RedirectToAction("Details", new { postId = review.PostId});
}
else
{
ModelState.AddModelError("ReviewErrors", "some error occured");
return RedirectToAction("Create", new { uniqueUri = Request.RequestContext.RouteData.Values["uniqueUri"]});
}
}
Wenn die Validierung erfolgreich ist, leite ich auf eine andere Seite um (Bestätigung).
Wenn ein Fehler auftritt, muss ich die gleiche Seite mit dem Fehler anzeigen.
Wenn ich das tue return View()
, wird der Fehler angezeigt, aber wenn ich es tue return RedirectToAction
(wie oben), verliert es die Modellfehler.
Ich bin nicht überrascht von dem Problem und frage mich nur, wie ihr damit umgeht.
Ich könnte natürlich nur dieselbe Ansicht anstelle der Umleitung zurückgeben, aber ich habe Logik in der "Erstellen" -Methode, die die Ansichtsdaten auffüllt, die ich duplizieren müsste.
Irgendwelche Vorschläge?
Create
Methode, die ViewData auffüllt, und rufen Sie sie in derCreate
GET-Methode sowie im Zweig für fehlgeschlagene Validierung in derCreate
POST-Methode auf.Create
Dinge in meiner Ansicht zu füllen . Ich habe sie einfach in eine Methode eingefügtpopulateStuff
, die ich sowohl in theGET
als auch in fail aufrufePOST
.Antworten:
Sie müssen dieselbe Instanz von
Review
für IhreHttpGet
Aktion haben. Dazu sollten Sie ein ObjektReview review
in der temporären Variablen IhrerHttpPost
Aktion speichern und es dann bei derHttpGet
Aktion wiederherstellen .Wenn dies auch dann funktionieren soll, wenn der Browser nach der ersten Ausführung der
HttpGet
Aktion aktualisiert wird , können Sie Folgendes tun:Andernfalls ist das Objekt der Schaltfläche "Aktualisieren"
review
leer, da keine Daten vorhanden sindTempData["Review"]
.quelle
TempData["ModelState"] = ModelState;
und mit wiederherstelltModelState.Merge((ModelStateDictionary)TempData["ModelState"]);
, dann würde es funktionierenreturn Create(uniqueUri)
wenn die Validierung im POST fehlschlägt? Da ModelState-Werte Vorrang vor dem an die Ansicht übergebenen ViewModel haben, sollten die veröffentlichten Daten weiterhin erhalten bleiben.Ich musste dieses Problem heute selbst lösen und bin auf diese Frage gestoßen.
Einige der Antworten sind nützlich (mithilfe von TempData), beantworten jedoch die vorliegende Frage nicht wirklich.
Der beste Rat, den ich gefunden habe, war in diesem Blog-Beitrag:
http://www.jefclaes.be/2012/06/persisting-model-state-when-using-prg.html
Verwenden Sie TempData grundsätzlich, um das ModelState-Objekt zu speichern und wiederherzustellen. Es ist jedoch viel sauberer, wenn Sie dies in Attribute abstrahieren.
Z.B
Dann können Sie gemäß Ihrem Beispiel den ModelState wie folgt speichern / wiederherstellen:
Wenn Sie das Modell auch in TempData weitergeben möchten (wie von bigb vorgeschlagen), können Sie dies auch weiterhin tun.
quelle
Warum nicht eine private Funktion mit der Logik in der Methode "Create" erstellen und diese Methode sowohl von der Get- als auch von der Post-Methode aufrufen und einfach View () zurückgeben?
quelle
return Create(new { uniqueUri = ... });
Ihre Logik bleibt trocken (ähnlich wie beim AufrufenRedirectToAction
), aber ohne die Probleme, die durch die Umleitung entstehen, wie z Verlieren Sie Ihren ModelState.ich könnte benutzen
TempData["Errors"]
TempData werden über Aktionen hinweg übergeben, wobei Daten 1 Mal beibehalten werden.
quelle
Ich schlage vor, dass Sie die Ansicht zurückgeben und eine Duplizierung über ein Attribut für die Aktion vermeiden. Hier ist ein Beispiel für das Auffüllen zum Anzeigen von Daten. Mit Ihrer Methode zum Erstellen von Methoden können Sie etwas Ähnliches tun.
Hier ist ein Beispiel:
quelle
Ich habe eine Methode, die temporären Daten den Modellstatus hinzufügt. Ich habe dann eine Methode in meinem Basis-Controller, die temporäre Daten auf Fehler überprüft. Wenn sie vorhanden sind, werden sie wieder zu ModelState hinzugefügt.
quelle
Mein Szenario ist etwas komplizierter, da ich das PRG-Muster verwende, sodass sich mein ViewModel ("SummaryVM") in TempData befindet und auf meinem Zusammenfassungsbildschirm angezeigt wird. Auf dieser Seite befindet sich ein kleines Formular, mit dem Sie Informationen an eine andere Aktion senden können. Die Komplikation ist darauf zurückzuführen, dass der Benutzer einige Felder in SummaryVM auf dieser Seite bearbeiten muss.
Summary.cshtml enthält die Validierungszusammenfassung, die die von uns erstellten ModelState-Fehler abfängt.
Mein Formular muss jetzt auf eine HttpPost-Aktion für Summary () POSTEN. Ich habe ein weiteres sehr kleines ViewModel, um bearbeitete Felder darzustellen, und die Modellbindung wird mir diese zur Verfügung stellen.
Die neue Form:
und die Aktion ...
Hier mache ich eine Validierung und stelle eine schlechte Eingabe fest, daher muss ich mit den Fehlern zur Seite "Zusammenfassung" zurückkehren. Dafür verwende ich TempData, das eine Umleitung überlebt. Wenn es kein Problem mit den Daten gibt, ersetze ich das SummaryVM-Objekt durch eine Kopie (aber die bearbeiteten Felder wurden natürlich geändert) und führe dann eine RedirectToAction ("NextAction") durch.
Die Aktion "Summary Controller", bei der alles beginnt, sucht nach Fehlern in den Tempdata und fügt sie dem Modellstatus hinzu.
quelle
Microsoft hat die Möglichkeit zum Speichern komplexer Datentypen in TempData entfernt, sodass die vorherigen Antworten nicht mehr funktionieren. Sie können nur einfache Typen wie Zeichenfolgen speichern. Ich habe die Antwort von @ asgeo1 so geändert, dass sie wie erwartet funktioniert.
Von hier aus können Sie bei Bedarf einfach die erforderlichen Datenanmerkungen zu einer Controller-Methode hinzufügen.
quelle
Ich ziehe es vor, meinem ViewModel eine Methode hinzuzufügen, die die Standardwerte auffüllt:
Dann nenne ich es, wann immer ich die Originaldaten wie folgt brauche:
quelle