42 votes

Bug possible dans ASP.NET MVC avec remplacement des valeurs de formulaire

Je semble avoir un problème avec ASP.NET MVC en ce que, si j'ai plus d'un formulaire sur une page qui utilise le même nom de chacun, mais aussi différents types (radio/caché/etc), puis, lors de la première forme de poteaux (je choisir le 'Date' bouton radio par exemple), si la forme est un nouveau rendu (dire que la partie de la page de résultats), Me semble que j'ai le problème que la valeur cachée de la SearchType sur les autres formes est changé à la dernière valeur du bouton radio (dans ce cas, SearchType.Nom).

Ci-dessous un exemple de formulaire pour les fins de réduction.

<% Html.BeginForm("Search", "Search", FormMethod.Post); %>
  <%= Html.RadioButton("SearchType", SearchType.Date, true) %>
  <%= Html.RadioButton("SearchType", SearchType.Name) %>
  <input type="submit" name="submitForm" value="Submit" />
<% Html.EndForm(); %>

<% Html.BeginForm("Search", "Search", FormMethod.Post); %>
  <%= Html.Hidden("SearchType", SearchType.Colour) %>
  <input type="submit" name="submitForm" value="Submit" />
<% Html.EndForm(); %>

<% Html.BeginForm("Search", "Search", FormMethod.Post); %>
  <%= Html.Hidden("SearchType", SearchType.Reference) %>
  <input type="submit" name="submitForm" value="Submit" />
<% Html.EndForm(); %>

Résultant source de la page (ce qui serait une partie de la page de résultats)

<form action="/Search/Search" method="post">
  <input type="radio" name="SearchType" value="Date" />
  <input type="radio" name="SearchType" value="Name" />
  <input type="submit" name="submitForm" value="Submit" />
</form>

<form action="/Search/Search" method="post">
  <input type="hidden" name="SearchType" value="Name" /> <!-- Should be Colour -->
  <input type="submit" name="submitForm" value="Submit" />
</form>

<form action="/Search/Search" method="post">
  <input type="hidden" name="SearchType" value="Name" /> <!-- Should be Reference -->
  <input type="submit" name="submitForm" value="Submit" />
</form>

S'il vous plaît pouvez quelqu'un avec la RC1 confirmer cela?

C'est peut-être parce que je suis en utilisant un enum. Je ne sais pas. Je dois ajouter que je peux contourner ce problème en utilisant la fonction "manuel" input () balises pour les champs cachés, mais si j'utilise MVC balises (<%= Html.Caché(...) %>), .NET MVC remplace à chaque fois.

Merci beaucoup.

Mise à jour:

J'ai vu ce bug de nouveau aujourd'hui. Il semble que cette culture sa tête lorsque vous revenez à une page validée et l'utilisation de MVC ensemble cachés balises de formulaire avec le helper Html. J'ai contacté Phil Haack à ce sujet, parce que je ne sais pas à qui s'adresser, et je ne crois pas que cela devrait être à un comportement attendu comme spécifié par David.

36voto

Haacked Points 31070

Oui, ce problème est actuellement à la conception. Même si vous êtes explicitement les valeurs de réglage, si vous publiez vers la même URL, nous recherchons dans le modèle de l'état et de l'utilisation de la valeur. En général, ceci nous permet d'afficher la valeur que vous avez soumis sur la publication, plutôt que la valeur d'origine.

Il y a deux solutions possibles. #1, l'utilisation des noms uniques pour chacun des champs. Notez que nous avons, par défaut, utilisez le nom que vous spécifiez l'id de l'élément HTML. C'est le code HTML incorrect à plusieurs éléments ont le même id. Donc, en utilisant des noms uniques est une bonne pratique.

Une autre solution est de ne pas utiliser le Caché helper. Il semble que vous n'avez vraiment pas besoin. Au lieu de cela, vous pourriez faire ceci:

<input type="hidden" name="the-name" 
  value="<%= Html.AttributeEncode(Model.Value) %>" />

Bien sûr, comme je pense, sur cette de plus, la modification de la valeur basée sur une publication de sens que pour les zones de texte, mais moins de sens pour les entrées. Nous ne pouvons pas changer cela pour v1.0, mais je vais y réfléchir pour la v2. Mais nous avons besoin de réfléchir soigneusement les implications d'un tel changement.

6voto

user183460 Points 1

Je viens de tomber sur une même question. Html helpers comme TextBox() priorité pour les valeurs passées semblent se comporter exactement à l'opposé de ce que j'ai déduit à partir de la Documentation où il est dit:

La valeur de la saisie de texte de l'élément. Si cette valeur est nulle référence (Nothing en Visual Basic), la valeur de l'élément est récupéré à partir le ViewDataDictionary objet. Si aucune valeur n'existe, la valeur est extrait de la ModelStateDictionary objet.

Pour moi, j'ai lu que la valeur, si le passé est utilisé. Mais la lecture de TextBox() source:

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

semble indiquer que la commande est à l'exact opposé de ce qui est documenté. Ordre semble être:

  1. ModelState
  2. ViewData
  3. Valeur (passé dans la zone de texte() par l'appelant)

6voto

Mark S Points 93

Heads-up - ce bogue existe toujours dans MVC 3. J'utilise la syntaxe de balisage Razor (comme si cela comptait vraiment), mais j'ai rencontré le même bogue avec une boucle foreach qui produisait la même valeur pour une propriété d'objet à chaque fois.

5voto

David Points 12145

Ce serait le comportement attendu - MVC n'utilise pas un état d'affichage ou d'autres derrière votre dos astuces pour transmettre des informations supplémentaires dans la forme, de sorte qu'il n'a aucune idée de la forme que vous avez soumis (le nom du formulaire ne fait pas partie de la base des données présentées, seulement une liste de paires nom/valeur).

Si MVC rend le formulaire de retour, c'est tout simplement pour vérifier si une valeur soumise avec le même nom existe - encore une fois, il n'a aucun moyen de savoir quelle forme d'une valeur nommée venus, ou même de ce type de contrôle qu'il a été (si vous utilisez une radio, d'un texte ou caché, c'est tout simplement le nom=valeur lors de ses soumis par HTTP).

4voto

jorge Points 41
foreach (var s in ModelState.Keys.ToList())
                if (s.StartsWith("detalleProductos"))
                    ModelState.Remove(s);

ModelState.Remove("TimeStamp");
ModelState.Remove("OtherOfendingHiddenFieldNamePostedToSamePage1");
ModelState.Remove("OtherOfendingHiddenFieldNamePostedToSamePage2");

return View(model);

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