5 votes

ASP.Net MVC ModelState / Html.TextBox problème de postback

J'ai un problème qui apparaît dans un formulaire que j'essaie de poster. Dans le cas où le formulaire n'est pas validé, j'emprunte la voie standard en appelant ModelState.AddModelError() puis de renvoyer un résultat d'affichage.

Le problème est que les aides HTML.* sont censées reprendre la valeur affichée lors du rendu et je remarque que mes champs de texte le font UNIQUEMENT si je les inclus dans la liste des paramètres de l'action de retour, ce qui ne devrait pas être nécessaire étant donné que certains formulaires ont beaucoup trop de champs pour vouloir les lister tous comme paramètres.

Mon code d'action est en gros :

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult EditDataDefinition(long? id, string name)
{
    var dataDefinition = ...

    // do some validation stuff
    if (!ModelState.IsValid)
    {
        // manually set checkbox fields via ViewData seeing as this STILL doesn't work in MC 1.0 :P
        // ...
        return View(dataDefinition);
    }

}

Maintenant, dataDefinition (qui est une entité LINQ to SQL) a un champ MinVolume est traitée dans la vue par cette ligne :

Minimum: <%= Html.TextBox("MinVolume", null, new { size = 5 })%>

Pourtant, lorsque la vue est rendue après l'échec de la validation du ModelState, la valeur saisie dans la page originale que nous avons affichée n'est pas préservée À MOINS que je ne l'inclue comme paramètre dans la méthode de retour. Littéralement, je peux "résoudre le problème" en faisant ceci :

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult EditDataDefinition(long? id, string name, string minVolume)

Pour une raison quelconque, cela forcera la valeur du champ à être préservée. Cela me semble stupide car mon formulaire contient bien plus de valeurs que ce seul champ et je ne devrais pas avoir à ajouter un paramètre pour ce seul champ.

Des idées ?

6voto

Jenea Points 2702

Oh mec, je viens d'améliorer le design de mon application. Le problème se produit parce que vous avez une validation personnalisée (j'en ai une aussi). Vous devez ajouter après

ModelState.AddModelError()

ce

ModelState.SetModelValue("MinVolume", ValueProvider["MinVolume"]);

En vue, il doit être

Mimum:<%=Html.Textbox("MinVolume")%>

Je ne sais toujours pas pourquoi ça marche, mais ça a marché pour moi.

4voto

cottsak Points 5490

Se pourrait-il que votre code :

<%= Html.TextBox("MinVolume", null, new { size = 5 })%>

..a le null pour la valeur par défaut param ? Peut-être que si vous changez le null a Model.MinVolume la valeur sera conservée. Comme ceci :

<%= Html.TextBox("MinVolume", Model.MinVolume, new { size = 5 })%>

Je ne suis pas sûr que votre action renvoie la valeur MinVolume dans le modèle tho. Si c'est le cas, ce qui précède devrait fonctionner. Sinon, vous devrez peut-être remanier légèrement l'action.

3voto

tvanfosson Points 268301

Quelle est la clé que vous utilisez lorsque vous définissez la valeur dans le ModelState en cas d'erreur ? Le code qui définit le paramètre de valeur pour un TextBox ressemble à ceci :

Partie pertinente de la code du cadre téléchargé .

string attemptedValue = (string)htmlHelper.GetModelStateValue(name, typeof(string));
tagBuilder.MergeAttribute("value", attemptedValue ?? ((useViewData) ? htmlHelper.EvalString(name) : valueParameter), isExplicitValue);

Comme vous pouvez le voir, si la valeur de la tentative existe, il l'utilisera - mais seulement si la même clé est disponible.

Je sais que cela fonctionne car j'ai une action qui ne prend aucun paramètre et obtient les valeurs directement du ValueProvider et elle utilise AddModelError pour indiquer les erreurs de validation. Je suis sûr que les valeurs de mes TextBoxes sont conservées.

EDIT : Pour que les valeurs soient retenues, elles doivent être associées au modèle d'une manière ou d'une autre. Une façon de le faire est de les ajouter à la liste des paramètres. Une autre façon est d'utiliser UpdateModel (avec les noms des paramètres dans la liste blanche ou sans liste blanche). Une troisième façon est d'ajouter le paramètre explicitement au modèle comme dans la réponse de @Jenea. Étant donné que l'aide ne fait que tirer parti de l'état du modèle, les paramètres doivent y être présents pour que les valeurs soient conservées. Il ne regarde pas la propriété Form de la requête.

0voto

diadiora Points 448

Si je comprends bien, la solution est la suivante :

[Transaction]
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult EditDataDefinition(int id, FormCollection form)
{
    T itemToUpdate = repository.Get(id);
    UpdateModel(itemToUpdate, form.ToValueProvider());

    if (itemToUpdate.IsValid())
    {
        repository.SaveOrUpdate(itemToUpdate);
        return Json(ValidationResultToJson(itemToUpdate.ValidationResults()));
    }

    repository.DbContext.RollbackTransaction();
    return Json(ValidationResultToJson(itemToUpdate.ValidationResults()));
}

Bonne chance !

0voto

Jenea Points 2702

Une autre solution consiste à taper dans view :

<%var minVolume=Request["MinVolume"]??"";%>
<%=Html.Textbox("MinVolume",minVolume,new {size=5})%>

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X