Quelqu'un peut-il me donner une définition succincte du rôle de ModelState dans Asp.net MVC (ou un lien vers un). En particulier, j'ai besoin de savoir dans quelles situations il est nécessaire ou souhaitable d'appeler ModelState.Clear()
.
Peu ouvert, hein ... désolé, je pense que cela pourrait aider si vous disiez ce que je fais réellement:
J'ai une action d'édition sur un contrôleur appelé "Page". Quand je vois pour la première fois le formulaire pour modifier les détails de la page, tout se charge correctement (liaison à un objet "MyCmsPage"). Ensuite, je clique sur un bouton qui génère une valeur pour l'un des champs de l'objet MyCmsPage ( MyCmsPage.SeoTitle
). Il génère bien et met à jour l'objet, puis je renvoie le résultat de l'action avec l'objet de page nouvellement modifié et j'attends que la zone de texte appropriée (rendue à l'aide de <%= Html.TextBox("seoTitle", page.SeoTitle)%>
) soit mise à jour ... mais hélas, elle affiche la valeur de l'ancien modèle chargé.
Je l'ai contourné en utilisant ModelState.Clear()
mais j'ai besoin de savoir pourquoi / comment cela a fonctionné, donc je ne le fais pas aveuglément.
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>
la source
Réponses:
Je pense que c'est un bogue dans MVC. J'ai lutté avec ce problème pendant des heures aujourd'hui.
Compte tenu de ceci:
La vue est rendue avec le modèle d'origine, ignorant les modifications. Alors j'ai pensé, peut-être que ça ne m'aime pas d'utiliser le même modèle, alors j'ai essayé comme ça:
Et toujours la vue est rendue avec le modèle d'origine. Ce qui est étrange, c'est que lorsque je mets un point d'arrêt dans la vue et que j'examine le modèle, il a la valeur modifiée. Mais le flux de réponse a les anciennes valeurs.
Finalement, j'ai découvert le même travail que vous avez fait:
Fonctionne comme prévu.
Je ne pense pas que ce soit une «fonctionnalité», n'est-ce pas?
la source
Mettre à jour:
View()
d'une action POST. Utilisez plutôt PRG et redirigez vers un GET si l'action réussit.View()
d'une action POST, faites - le pour la validation du formulaire, et faire le chemin MVC est conçu en utilisant le haut dans les aides. Si vous le faites de cette façon, vous ne devriez pas avoir besoin d'utiliser.Clear()
ModelState
car vous ne devriez pas l'utiliser de toute façon.Ancienne réponse:
ModelState dans MVC est principalement utilisé pour décrire l'état d'un objet de modèle en grande partie par rapport à savoir si cet objet est valide ou non. Ce tutoriel devrait en expliquer beaucoup.
En règle générale, vous ne devriez pas avoir besoin d'effacer le ModelState car il est géré par le moteur MVC pour vous. Le supprimer manuellement peut entraîner des résultats indésirables lorsque vous essayez de respecter les meilleures pratiques de validation MVC.
Il semble que vous essayez de définir une valeur par défaut pour le titre. Cela devrait être fait lorsque l'objet du modèle est instancié (couche de domaine quelque part ou dans l'objet lui-même - ctor sans paramètre), sur l'action get de telle sorte qu'il descende à la page la 1ère fois ou complètement sur le client (via ajax ou quelque chose) afin qu'il apparaisse comme si l'utilisateur l'a entré et il revient avec la collection de formulaires publiée. Certains comment ce comportement est à l' origine bizarre qui pourrait se traduire par une votre approche d'ajouter cette valeur à la réception d'une collection de formes (dans l'action POST // Edit)
.Clear()
apparaissant au travail pour vous. Croyez-moi, vous ne voulez pas utiliser le clair. Essayez l'une des autres idées.la source
Si vous souhaitez effacer une valeur pour un champ individuel, j'ai trouvé la technique suivante utile.
Remarque: remplacez «Clé» par le nom du champ que vous souhaitez réinitialiser.
la source
Eh bien, le ModelState contient essentiellement l'état actuel du modèle en termes de validation, il tient
ModelErrorCollection: représente les erreurs lorsque le modèle essaie de lier les valeurs. ex.
ou comme un paramètre dans ActionResult
ValueProviderResult : contient les détails sur la tentative de liaison au modèle. ex. AttemptedValue, Culture, RawValue .
La méthode Clear () doit être utilisée avec prudence car elle peut conduire à des résultats non détectés. Et vous perdrez quelques belles propriétés du ModelState comme AttemptedValue, ceci est utilisé par MVC en arrière-plan pour repeupler les valeurs du formulaire en cas d'erreur.
la source
J'ai eu une instance où je voulais mettre à jour le modèle d'un formulaire résumé, et je ne voulais pas «rediriger vers l'action» pour des raisons de performance. Les valeurs précédentes des champs masqués étaient conservées sur mon modèle mis à jour - provoquant toutes sortes de problèmes !.
Quelques lignes de code ont rapidement identifié les éléments dans ModelState que je voulais supprimer (après validation), donc les nouvelles valeurs ont été utilisées sous la forme: -
la source
Eh bien, beaucoup d'entre nous semblent avoir été mordus par cela, et bien que la raison pour laquelle cela se produit soit logique, j'avais besoin d'un moyen de m'assurer que la valeur de mon modèle était affichée, et non ModelState.
Certains ont suggéré
ModelState.Remove(string key)
, mais ce quikey
devrait être n'est pas évident , en particulier pour les modèles imbriqués. Voici quelques méthodes que j'ai mises au point pour vous aider.La
RemoveStateFor
méthode prendra unModelStateDictionary
, un modèle et une expression pour la propriété souhaitée et la supprimera.HiddenForModel
peut être utilisé dans votre vue pour créer un champ d'entrée masqué en utilisant uniquement la valeur du modèle, en supprimant d'abord son entrée ModelState. (Cela pourrait facilement être étendu pour les autres méthodes d'extension d'assistance).Appel d'un contrôleur comme celui-ci:
ou depuis une vue comme celle-ci:
Il utilise
System.Web.Mvc.ExpressionHelper
pour obtenir le nom de la propriété ModelState.la source
Je voulais mettre à jour ou réinitialiser une valeur si elle ne validait pas tout à fait et j'ai rencontré ce problème.
La réponse simple, ModelState.Remove, est… problématique… parce que si vous utilisez des helpers, vous ne connaissez pas vraiment le nom (sauf si vous vous en tenez à la convention de dénomination). Sauf si vous créez une fonction que votre assistant personnalisé et votre contrôleur peuvent utiliser pour obtenir un nom.
Cette fonctionnalité aurait dû être implémentée en option sur l'assistant, où, par défaut, elle ne le fait pas , mais si vous vouliez que l'entrée non acceptée soit réaffiche, vous pouvez simplement le dire.
Mais au moins je comprends le problème maintenant;).
la source
Remove()
la bonne clé.J'ai compris à la fin. Mon ModelBinder personnalisé qui n'était pas en cours d'enregistrement et fait ceci:
Donc, quelque chose que faisait la liaison de modèle par défaut devait être à l'origine du problème. Je ne sais pas quoi, mais mon problème est au moins résolu maintenant que mon classeur de modèles personnalisés est en cours d'enregistrement.
la source
Généralement, lorsque vous vous retrouvez à lutter contre un cadre de pratiques standard, il est temps de reconsidérer votre approche. Dans ce cas, le comportement de ModelState. Par exemple, lorsque vous ne voulez pas l'état du modèle après un POST, envisagez une redirection vers le fichier get.
MODIFIÉ pour répondre au commentaire sur la culture:
Voici ce que j'utilise pour gérer une application MVC multiculturelle. Tout d'abord, les sous-classes du gestionnaire d'itinéraire:
Et voici comment je câbler les itinéraires. Après avoir créé les routes, j'ajoute mon sous-agent (example.com/subagent1, example.com/subagent2, etc.) puis le code de culture. Si vous n'avez besoin que de la culture, supprimez simplement le sous-agent des gestionnaires de routes et des routes.
la source
Eh bien, cela semblait fonctionner sur ma page Razor et n'a même jamais fait un aller-retour vers le fichier .cs. C'est une vieille méthode html. Cela pourrait être utile.
la source