web-dev-qa-db-fra.com

ASP.NET MVC: la valeur du champ masqué n'est pas rendue à l'aide de HtmlHelper.Hidden

Quelque chose d'assez étrange se passe avec mon application:

J'ai la propriété suivante dans mon ViewModel:

public int? StakeholderId { get; set; }

Il est rendu dans une vue partielle comme suit:

<%= Html.Hidden("StakeholderId", Model.StakeholderId) %>

Le formulaire est soumis et l'action de contrôleur appropriée génère un identifiant et met à jour le modèle, avant de renvoyer la même vue avec le modèle mis à jour

Le problème que je rencontre est que le champ caché n'a rien dans son attribut "value" rendu la deuxième fois même si StakeholderId a maintenant une valeur.

Si je viens de sortir la valeur seule, elle apparaît sur la page, donc je l'ai pour rendre la valeur en faisant ceci:

<input type="hidden" id="StakeholderId" name="stakeholderId" value="<%: Model.StakeholderId %>" />

Mais c'est assez étrange que l'assistant ne récupère pas la valeur mise à jour?

(J'utilise jQuery pour soumettre des formulaires et rendre les résultats de l'action en divs, mais j'ai vérifié et le HTML que je récupère est déjà faux avant que jQuery ne fasse quoi que ce soit avec cela, donc je ne pense pas que cela ait beaucoup à voir avec n'importe quoi)

MISE À JOUR

J'ai depuis découvert que je peux également effacer la clé ModelState appropriée avant que mon action de contrôleur retourne la vue partielle.

70
Veli Gebrev

L'assistant recherchera d'abord les valeurs POSTed et les utilisera. Lorsque vous publierez le formulaire, il récupérera l'ancienne valeur de l'ID. Votre solution de contournement est correcte.

60
Darin Dimitrov

ADDENDUM: plusieurs formulaires HTML, par exemple, dans une grille

En complément de ce problème, une chose à laquelle il faut être TRÈS prudent est d'utiliser plusieurs formulaires sur la même page, par exemple, dans une grille, par exemple un généré à l'aide d'Ajax.BeginForm.

Vous pourriez être tenté d'écrire quelque chose comme:

@foreach (var username in Model.TutorUserNames)
        {
            <tr>
                <td>
                    @Html.ActionLink(username, MVC.Admin.TutorEditor.Details(username))
                </td>
                <td>
                    @using (Ajax.BeginForm("DeleteTutor", "Members",
                        new AjaxOptions
                        {
                            UpdateTargetId = "AdminBlock",
                            OnBegin = "isValidPleaseWait",
                            LoadingElementId = "PleaseWait"
                        },
                        new { name = "DeleteTutorForm", id = "DeleteTutorForm" }))
                    {    
                        <input type="submit" value="Delete" />
                        @Html.Hidden("TutorName", username)
                    }
                </td>
            </tr>
        }

La ligne mortelle ici est:

@Html.Hidden("TutorName", username)

... et l'intention d'utiliser TutorName comme paramètre de votre action. PAR EXEMPLE:

public virtual ActionResult DeleteTutor(string TutorName){...}

Si vous faites cela, la mauvaise surprise pour laquelle vous êtes est que Html.Hidden ("TutorName", nom d'utilisateur), comme l'explique Darin Dimitrov, rendra la dernière valeur POSTed. C'est à dire, quelle que soit votre boucle, TOUS les éléments seront rendus avec le TutorName du dernier tuteur supprimé!

Le mot autour, dans la syntaxe Razor, consiste à remplacer l'appel @ Html.Hidden par une balise d'entrée explicite:

<input type="hidden" id="TutorName" name="TutorName" value='@username' />

Cela fonctionne comme prévu.

C'est à dire:

JAMAIS, JAMAIS UTILISER Html. Caché POUR PASSER UN PARAMÈTRE À VOS ACTIONS LORSQUE VOUS UTILISEZ PLUSIEURS FORMULAIRES DANS UNE GRILLE !!!

Avertissement final:

Lors de la construction de votre balise d'entrée cachée, vous devez inclure à la fois le nom et l'id, définis sur la même valeur, sinon, au moment de la rédaction (février 2011), cela ne fonctionnera pas correctement. Certainement pas dans Google Chrome. Tout ce que vous obtenez est un paramètre nul retourné si vous n'avez qu'un identifiant et aucun attribut de nom.

34
awrigley