Kann mir jemand eine kurze Definition der Rolle von ModelState in Asp.net MVC geben (oder einen Link zu einer). Insbesondere muss ich wissen, in welchen Situationen es notwendig oder wünschenswert ist, anzurufen ModelState.Clear()
.
Etwas offenes Ende huh ... Entschuldigung, ich denke, es könnte helfen, wenn ich Ihnen sage, was ich akut mache:
Ich habe eine Aktion zum Bearbeiten auf einem Controller namens "Seite". Wenn ich das Formular zum Ändern der Details der Seite zum ersten Mal sehe, wird alles gut geladen (Bindung an ein "MyCmsPage" -Objekt). Dann klicke ich auf eine Schaltfläche, die einen Wert für eines der Felder des MyCmsPage-Objekts generiert ( MyCmsPage.SeoTitle
). Es generiert eine Geldstrafe und aktualisiert das Objekt. Anschließend gebe ich das Aktionsergebnis mit dem neu geänderten Seitenobjekt zurück und erwarte, dass das relevante Textfeld (gerendert mit <%= Html.TextBox("seoTitle", page.SeoTitle)%>
) aktualisiert wird. Leider wird der Wert des alten Modells angezeigt, das geladen wurde.
Ich habe es mit verwendet, ModelState.Clear()
aber ich muss wissen, warum / wie es funktioniert hat, damit ich es nicht nur blind mache.
PageController:
[AcceptVerbs("POST")]
public ActionResult Edit(MyCmsPage page, string submitButton)
{
// add the seoTitle to the current page object
page.GenerateSeoTitle();
// why must I do this?
ModelState.Clear();
// return the modified page object
return View(page);
}
Aspx:
<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<MyCmsPage>" %>
....
<div class="c">
<label for="seoTitle">
Seo Title</label>
<%= Html.TextBox("seoTitle", page.SeoTitle)%>
<input type="submit" value="Generate Seo Title" name="submitButton" />
</div>
quelle
Antworten:
Ich denke, es ist ein Fehler in MVC. Ich hatte heute stundenlang mit diesem Problem zu kämpfen.
Angesichts dessen:
Die Ansicht wird mit dem Originalmodell gerendert, wobei die Änderungen ignoriert werden. Also dachte ich, vielleicht mag es mich nicht, dasselbe Modell zu verwenden, also habe ich es so versucht:
Und dennoch wird die Ansicht mit dem Originalmodell gerendert. Was seltsam ist, wenn ich einen Haltepunkt in die Ansicht setze und das Modell untersuche, hat es den geänderten Wert. Der Antwortstrom hat jedoch die alten Werte.
Schließlich entdeckte ich die gleiche Arbeit wie Sie:
Funktioniert wie erwartet.
Ich denke nicht, dass dies ein "Feature" ist, oder?
quelle
Aktualisieren:
View()
von einer POST-Aktion zurückzukehren. Verwenden Sie stattdessen PRG und leiten Sie zu einem GET um, wenn die Aktion erfolgreich ist.View()
von einer POST - Aktion, tun es für Formularvalidierung, und tun es die Art und Weise MVC konzipiert in Helfer die eingebaute verwenden. Wenn Sie es so machen, sollten Sie es nicht brauchen.Clear()
ModelState
Sie dies, da Sie ihn sowieso nicht verwenden sollten.Alte Antwort:
ModelState in MVC wird hauptsächlich verwendet, um den Status eines Modellobjekts weitgehend in Bezug darauf zu beschreiben, ob dieses Objekt gültig ist oder nicht. Dieses Tutorial sollte viel erklären.
Im Allgemeinen sollten Sie den ModelState nicht löschen müssen, da er von der MVC-Engine für Sie verwaltet wird. Das manuelle Löschen kann zu unerwünschten Ergebnissen führen, wenn versucht wird, die Best Practices für die MVC-Validierung einzuhalten.
Es scheint, dass Sie versuchen, einen Standardwert für den Titel festzulegen. Dies sollte erfolgen, wenn das Modellobjekt instanziiert wird (Domänenschicht irgendwo oder im Objekt selbst - parameterloser Ctor), und zwar bei der Aktion get so, dass es beim ersten Mal auf die Seite oder vollständig auf dem Client (über Ajax oder etwas anderes) gelangt. so dass es so aussieht, als ob der Benutzer es eingegeben hat und es mit der Sammlung der veröffentlichten Formulare zurückkommt. Einige , wie Sie Ihr Ansatz , diesen Wertes der Zugabe auf dem Empfang einer Formen Sammlung (in der POST - Aktion // Edit) verursachen dieses bizarre Verhalten , das in einer Folge könnte
.Clear()
erscheinen , an der Arbeit für Sie. Vertrauen Sie mir - Sie wollen nicht die klare verwenden. Probieren Sie eine der anderen Ideen aus.quelle
Wenn Sie einen Wert für ein einzelnes Feld löschen möchten, fand ich die folgende Technik hilfreich.
Hinweis: Ändern Sie "Schlüssel" in den Namen des Feldes, das Sie zurücksetzen möchten.
quelle
Nun, der ModelState enthält im Grunde genommen den aktuellen Status des Modells in Bezug auf die Validierung
ModelErrorCollection: Stellen Sie die Fehler dar, wenn das Modell versucht, die Werte zu binden. Ex.
oder wie ein Parameter im ActionResult
ValueProviderResult : Halten Sie die Details der versuchten Bindung an das Modell fest. Ex. AttemptedValue, Culture, RawValue .
Die Methode clear () muss mit Vorsicht angewendet werden, da dies zu unerwarteten Ergebnissen führen kann. Und Sie verlieren einige nette Eigenschaften des ModelState wie AttemptedValue. Dies wird von MVC im Hintergrund verwendet, um die Formularwerte im Fehlerfall neu zu füllen.
quelle
Ich hatte eine Instanz, in der ich das Modell eines summierten Formulars aktualisieren wollte und aus Leistungsgründen nicht auf Aktion umleiten wollte. Frühere Werte von ausgeblendeten Feldern wurden in meinem aktualisierten Modell beibehalten - was zu einer Vielzahl von Problemen führte!.
Einige Codezeilen identifizierten bald die Elemente in ModelState, die ich (nach der Validierung) entfernen wollte, sodass die neuen Werte in der folgenden Form verwendet wurden:
quelle
Nun, viele von uns scheinen davon gebissen worden zu sein, und obwohl der Grund dafür sinnvoll ist, brauchte ich einen Weg, um sicherzustellen, dass der Wert meines Modells angezeigt wurde und nicht ModelState.
Einige haben vorgeschlagen
ModelState.Remove(string key)
, aber es ist nicht offensichtlich, waskey
sein sollte, insbesondere für verschachtelte Modelle. Hier sind einige Methoden, die ich entwickelt habe, um dies zu unterstützen.Die
RemoveStateFor
Methode nimmt einModelStateDictionary
, ein Modell und einen Ausdruck für die gewünschte Eigenschaft und entfernt sie.HiddenForModel
kann in Ihrer Ansicht verwendet werden, um ein verstecktes Eingabefeld zu erstellen, bei dem nur der Wert aus dem Modell verwendet wird, indem zuerst der ModelState-Eintrag entfernt wird. (Dies könnte leicht für die anderen Hilfserweiterungsmethoden erweitert werden).Anruf von einem Controller wie folgt:
oder aus einer solchen Sicht:
Es wird verwendet
System.Web.Mvc.ExpressionHelper
, um den Namen der ModelState-Eigenschaft abzurufen.quelle
Ich wollte einen Wert aktualisieren oder zurücksetzen, wenn er nicht vollständig validiert wurde, und bin auf dieses Problem gestoßen.
Die einfache Antwort, ModelState.Remove, ist problematisch, denn wenn Sie Helfer verwenden, kennen Sie den Namen nicht wirklich (es sei denn, Sie halten sich an die Namenskonvention). Es sei denn, Sie erstellen eine Funktion, mit der sowohl Ihr benutzerdefinierter Helfer als auch Ihr Controller einen Namen abrufen können.
Diese Funktion sollte als Option im Helper implementiert worden sein, wobei dies standardmäßig nicht der Fall ist. Wenn Sie jedoch möchten, dass die nicht akzeptierte Eingabe erneut angezeigt wird, können Sie dies einfach sagen.
Aber zumindest verstehe ich das Problem jetzt;).
quelle
Remove()
den richtigen Schlüssel zu finden.Habe es am Ende. Mein benutzerdefinierter ModelBinder, der nicht registriert wurde und dies tut:
Etwas, das die Standardmodellbindung tat, muss das Problem verursacht haben. Ich weiß nicht was, aber mein Problem ist zumindest behoben, nachdem mein benutzerdefinierter Modellordner registriert wurde.
quelle
Im Allgemeinen ist es an der Zeit, Ihren Ansatz zu überdenken, wenn Sie gegen Standardpraktiken kämpfen. In diesem Fall das Verhalten von ModelState. Wenn Sie beispielsweise nach einem POST keinen Modellstatus wünschen, ziehen Sie eine Umleitung zum get in Betracht.
BEARBEITET, um Kulturkommentar zu beantworten:
Hier ist, was ich verwende, um eine multikulturelle MVC-Anwendung zu handhaben. Zuerst die Unterklassen des Routenhandlers:
Und so verkabele ich die Routen. Nach dem Erstellen der Routen stelle ich meinem Subagenten (example.com/subagent1, example.com/subagent2 usw.) den Kulturcode voran. Wenn Sie nur die Kultur benötigen, entfernen Sie einfach den Subagenten aus den Routenhandlern und Routen.
quelle
Nun, das schien auf meiner Rasiermesserseite zu funktionieren und machte noch nie einen Rundgang zur CS-Datei. Dies ist ein alter HTML-Weg. Es könnte nützlich sein.
quelle