Comment gérez-vous la sortie d'un formulaire généré dynamiquement dans ASP.NET MVC?

StackOverflow https://stackoverflow.com/questions/223149

  •  03-07-2019
  •  | 
  •  

Question

Supposons que vous créez un formulaire à l'aide d'ASP.NET MVC comportant un nombre dynamique d'éléments de formulaire.

Par exemple, vous avez besoin d’une case à cocher pour chaque produit et le nombre de produits change tous les jours.

Comment géreriez-vous les données de formulaire qui seront retransmises au contrôleur? Vous ne pouvez pas configurer de paramètres sur la méthode d'action car vous ne savez pas combien de valeurs de formulaire vont revenir.

Était-ce utile?

La solution

Donnez simplement à chaque case à cocher une valeur de nom unique:

<input class="approveCheck" id="<%= "approveCheck" + recordId %>" 
 name="<%= "approveCheck" + recordId %>" type="checkbox" />

Ensuite, analysez la liste des valeurs de formulaire dans l'action, après soumission:

foreach (var key in Request.Form.Keys)
    {
        string keyString = key.ToString();
        if (keyString.StartsWith("approveCheck", StringComparison.OrdinalIgnoreCase))
        {
            string recNum = keyString.Substring(12, keyString.Length - 12);

            string approvedKey = Request.Form["approveCheck" + recNum];
            bool approved = !String.IsNullOrEmpty(approvedKey);
            // ...

Vous n'avez pas besoin de transmettre des valeurs de formulaire en tant qu'arguments; vous pouvez simplement les obtenir à partir de Request.Form.

Une autre option: rédigez un classeur de modèle pour modifier la liste en un type personnalisé pour la soumission du formulaire.

Autres conseils

Selon la réponse de Craig, c’est plus sûr. Il y a des bizarreries à poster plusieurs éléments de formulaire avec le même nom. J'ajouterais qu'il serait sage de résumer la logique qui rend la "collection" des contrôles d'une manière similaire à WebForms. Les formulaires Web ajoutent le nom du contrôle de conteneur et ajoutent un index. Par exemple, dans un répéteur, les éléments de formulaire à l'intérieur seraient nommés (quelque chose comme) RepeaterName_Element1, RepeaterName_Element2. Pour extraire les éléments, vous devez utiliser FindControl ou quelque chose du genre.

Selon les classeurs que vous utilisez, cela devrait fonctionner:

<%var i = 0;
  foreach (var product (IList<ProductSelection>)ViewData["products"]) {%>
      <%=Html.Hidden(string.Format("products[{0}].Id", i), product.Id)%>
      <%=Html.Checkbox(string.Format("products[{0}].Selected", i))%>
      <%=product.Name%><br/>
<%}%>

... ce qui produira quelque chose comme ceci en HTML (notez la notation du tableau sur les noms):

<input name="products[0].Id" type="hidden" value="123">
<input name="products[0].Selected" type="checkbox">
Widget
<input name="products[1].Id" type="hidden" value="987">
<input name="products[1].Selected" type="checkbox">
Gadget

... et la méthode du contrôleur qui gère la publication:

public ActionResult SelectProducts(IList<ProductSelection> products)
{
     ...
}

Lors de la liaison, le paramètre products contiendra deux instances de ProductSelection.

Un inconvénient est que je n'ai pas utilisé la nouvelle liaison par défaut pour les objets complexes. J'utilise plutôt le NameValueDeserializer ou CastleBind, tous deux de MvcContrib. Ils se comportent tous les deux de cette façon. Je suppose que la liaison dans la bêta fonctionnera de la même manière.

En fonction de vos données, vous pouvez générer une "CheckboxList" (ce qui n'est plus possible dans les versions les plus récentes) et utiliser un paramètre string [] , ou vous pouvez configurer plusieurs formulaires. et juste modifier l'action.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top