2017-07-31 2 views
1

Je Boucler dans un IEnumerable de mon modèle:MVC Html.HiddenFor dans un modèle de passage en boucle de retour au contrôleur

@model IEnumerable<Testing.Models.ProductItem> 
@{ 
    ViewBag.Title = "Buy Products"; 
} 

<div class="row"> 
    @foreach (var product in Model) 
    { 
     using (Html.BeginForm()) 
     { 
      @Html.HiddenFor(Model => product) 
      ... More Controls and stuff... 
      <input type="submit" value="Add To Kart" class="btn btn-info"> 

     } 

    } 
</div> 

et soumettre, je veux passer l'instance sélectionnée de mon modèle de retour à mon contrôleur:

[HttpPost] 
    public ActionResult Index(ProductItem product) 
    { 
     ... Do Stuff ... 
     return View(); 
    } 

Cependant j'ai essayé quelques petites choses, mais semblent toujours se passer nulle dans le contrôleur ... S'il vous plaît quelqu'un pourrait aider s'il vous plaît me diriger dans la bonne direction?

EDIT

Je ne fait besoin de l'instance de modèle complet que je peux obtenir ce dans le contrôleur de l'ID - donc je l'ai essayé les suivantes:

@model IEnumerable<Testing.Models.ProductItem> 
@{ 
    ViewBag.Title = "Buy Products"; 
} 

<div class="row"> 
    @foreach (var product in Model) 
    { 
     using (Html.BeginForm()) 
     { 
      @Html.HiddenFor(Model => product.ID) 
      @Html.TextBox("qty", "1", htmlAttributes: new { @style = "width: 30px;" }) 

      ... More Controls and stuff... 

      <input type="submit" value="Add To Kart" class="btn btn-info"> 

     } 

    } 
</div> 

qui messages à la contrôleur:

[HttpPost] 
public ActionResult Index([Bind(Include = "ID")] int? ID, [Bind(Include = "qty")] int? qty) 
{ 
    return null; 
} 

La zone de texte ne fait pas partie du modèle car elle est entrée par l'utilisateur - cette valeur est passée joliment dans l'action Cependant, je reçois toujours une valeur nulle pour l'ID dans le contrôle HiddenFor. Est-ce à voir avec le nom du contrôle? Je ne semble pas pouvoir ajouter un nom au contrôle HiddenFor.

Je sais que cela apporte un éclairage différent sur la question initiale, mais j'espère que vous pourrez toujours aider.

Je prends la note de la BeginForm étant à l'intérieur de la boucle - créer pour chaque élément dans la liste ... Y at-il une alternative facile à cette (notez que je ne l'ai pas encore essayé quoi que ce soit).

+0

Il existe plusieurs problèmes avec votre code. D'abord vous ne pouvez pas lier un objet complexe au contrôle de forme (vous devez lier chaque propriété si le modèle).Et avoir un formulaire pour chaque élément de la collection n'a pas de sens - vous ne pouvez soumettre qu'un formulaire à la fois et dans tous les cas, vous générez des entrées qui n'ont aucun lien avec votre modèle –

+0

Générez vos contrôles de formulaire dans un seul formulaire en utilisant une boucle 'for' ou' EditorTemplate' et soumettez-le tout en une action (référez-vous à [cette réponse] (http://stackoverflow.com/questions/30094047/html-table-to-ado-net-datatable/30094943#30094943)) ou si vous voulez mettre à jour un seul élément à la fois, utilisez ajax ou ayez un lien qui redirige votre vers une page pour l'édition de cet article –

+0

Merci à la fois ... À la lumière de cela, j'ai mis à jour la question passer l'ID au lieu du modèle complet. Si vous étiez en mesure de jeter un coup d'oeil et laissez-moi savoir vos pensées maintenant serait génial. – CJH

Répondre

2

Il semble que vous essayez d'utiliser HiddenFor sur un type complexe et cela ne fonctionnera pas. Vous devrez utiliser une propriété de ProductItem comme ProductId ou quelque chose comme ça, qui sera probablement un int ou Guid.

Maintenant que vous avez effacé la liaison complexe à un champ simple, vous remarquerez que votre nom est défini sur product.id et c'est pourquoi il est toujours null dans votre contrôleur. Vous ne pouvez pas remplacer l'attribut name avec caché pour, donc vous voulez changer votre code:

@foreach (var product in Model) 
{ 
    using (Html.BeginForm()) 
    { 
     @Html.Hidden("ID", product.ID) 
     @Html.TextBox("qty", "1", htmlAttributes: new { @style = "width: 30px;" }) 

     <input type="submit" value = "Add To Kart" class="btn btn-info"> 
    } 

} 
+0

Merci codepros ... À la lumière de cela, j'ai mis à jour la question un peu de passer l'ID au lieu du modèle complet. Si vous étiez en mesure de jeter un coup d'oeil et laissez-moi savoir vos pensées maintenant serait génial. – CJH

+0

Heya @CJH, HiddenFor va définir le nom et l'identifiant automatiquement. Vous pouvez remplacer l'ID, mais vous ne pouvez pas facilement remplacer le nom. Donc, pour obtenir la fonctionnalité que vous voulez, vous aurez envie d'utiliser Html.Hidden, par exemple: utilisant (Html.BeginForm()) { Html.Hidden ("ID", product.ID) Html. TextBox ("qty", "1", htmlAttributes: nouveau {style = "largeur: 30px;"}) } – coderpros

-1

au lieu du modèle => product.Id, essayez p => product.Id

@model IEnumerable<Testing.Models.ProductItem> 
    @{ 
     ViewBag.Title = "Buy Products"; 
    } 

    <div class="row"> 
    using (Html.BeginForm()) 
    { 
     @foreach (var product in Model) 
     { 
      @Html.HiddenFor(p => product.ID) 
      @Html.TextBox("qty", "1", htmlAttributes: new { @style = "width: 
      30px;" }) 

      ... More Controls and stuff...   

     } 
     <input type="submit" value="Add To Kart" class="btn btn-info"> 
    } 
    </div> 
+0

Cela rendrait toujours l'entrée cachée avec un nom de product.ID ce qui signifie que son contrôleur ne prendrait jamais la valeur (en fonction de la façon dont il est actuellement écrit). – coderpros

0

J'ai réussi à arriver à ma fonctionnalité désirée (à tort ou à raison) ce qui suit:

@model List<ShoppingKartTest.Models.ProductItem> 
@{ 
    ViewBag.Title = "Buy Products"; 
} 



@foreach (var item in Model) 
{ 
    using (Html.BeginForm()) 
    { 

     <input type="hidden" value="@item.ID" name="ID" /> 
     @Html.TextBox("qty", "1", new { @style = "width: 30px;" }) 


     <input type="submit" value="Add To Kart" class="btn btn-info"> 
    } 
} 

qui soumet correctement l'ID caché et le contenu de la zone de texte à l'action du contrôleur:

[HttpPost] 
public ActionResult Index(int ID, int qty) 
{ 
    //... Do stuff with parameters... 
    return View(); 
} 

Je serais intéressé d'avoir des commentaires à ce sujet. Je sais qu'on m'a dit plus haut que je ne devrais pas avoir mon BeginForm dans la boucle ... Mais ça marche pour moi.

+0

Il n'y a rien de "faux" avec ce code, en soi. Cela ressemble à peu près au code que je vous ai donné tôt ce matin. Les puristes ne prétendent pas que votre approche ne fonctionnera pas, mais qu'elle est laide et va à l'encontre des meilleures pratiques modernes/n'est pas évolutive. Votre code rend inutilement beaucoup de formulaires ouverts et ferme les balises qui gonflent votre page. Une approche plus correcte et moderne serait d'avoir un seul Html.BeginForm ou Ajax.BeginForm et d'avoir votre contrôleur accepter les clics 'ajouter au panier' via AJAX. – coderpros

+0

Merci pour le codepros de retour ... Je l'apprécie. Mon projet actuel ne va jamais voir un environnement de production et doit être utilisé uniquement comme un exemple fonctionnel donc je vais peut-être m'en tirer ... Cette fois ... – CJH

+1

Il y a beaucoup de choses qui sont mauvaises avec ce code. Vous n'êtes pas lié à un modèle, vous n'obtenez pas de validation et cela ne fonctionnera pas correctement si vous deviez retourner la vue. Pourquoi même utiliser MVC si vous allez écrire du code qui annule tous ses avantages. –