Reputation: 1594
I am looping through an IEnumerable of my model:
@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>
and on submit I want to pass the selected instance of my model back to my controller:
[HttpPost]
public ActionResult Index(ProductItem product)
{
... Do Stuff ...
return View();
}
However I have tried a few things but always seem to be getting null passed into the controller... Please could someone please help point me in the right direction?
EDIT
I dont actually need to the full model instance as I can get this within the controller from the ID - so I have tried the following:
@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>
which posts to the controller:
[HttpPost]
public ActionResult Index([Bind(Include = "ID")] int? ID, [Bind(Include = "qty")] int? qty)
{
return null;
}
The textbox is not part of the model as it is user input - this value is passed nicely into the actions parameter, however I am still getting a null for the ID in the HiddenFor control. Is this to do with the naming of the control? I dont seem to be able to add a name to the HiddenFor control.
I know this puts a different light on the original question but I am hoping you may still be able to help.
I take the note about the BeginForm being inside the loop - creating for each item in the list... Is there an easy alternative to this (note I haven't tried anything yet).
Upvotes: 1
Views: 2168
Reputation: 1594
I have managed to arrive at my desired functionality (rightly or wrongly) with the following:
@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">
}
}
Which correctly submits the Hidden ID and the contents of the Textbox to the Controller Action:
[HttpPost]
public ActionResult Index(int ID, int qty)
{
//... Do stuff with parameters...
return View();
}
I would be interested to hear any comments on this. I know that I was told above that I shouldn't have my BeginForm within the loop... But it just works for me.
Upvotes: 1
Reputation: 150
Instead of Model => product.Id, try 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>
Upvotes: -1
Reputation: 871
It sounds like you're trying to use HiddenFor on a complex type and that won't work. You'll need to use a property of ProductItem like ProductId or something like that, which will most likely be an int or Guid.
Now that you have cleared up the complex binding to a simple field, you'll notice that your name is being set to product.id and that is why it is always null in your controller. You can't override the name attribute with Hidden for, so you'll want to change your code to:
@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">
}
}
Upvotes: 2