1

The scenario is a shopping basket - the user will update a text box for the quantity and hit the update button. Currently, upon hitting the update button, the Action is hit but the model properties are all null.

My first thoughts are that there is some issue with the binding because the ids of the controls are changed for each row.

Are my thoughts correct? if so, how can I resolve this?

EDIT: I also tried to use a for loop, rather than foreach but that didn't work either. All my code is below:

<table class="order-table order-table-nomargin order-table-noborder hidden-xs hidden-sm">
  <thead>
    <tr><th>Products</th><th></th><th>Price</th><th>Qty.</th><th>Total</th></tr>
  </thead>
  <tbody>
    @foreach (Nop.Web.Models.Custom.CustomOrderLine ol in Model.Cart.OrderLines)
    {    
      @Html.DisplayFor(m => ol)
    }      
  </tbody>
</table> 

This is my displayFor Template:

@model Nop.Web.Models.Custom.CustomOrderLine
<tr>
    <td>
        <img alt="book image" src="@Model.Image.Media.Url"  width="100" />
    </td>
    <td>
        @Html.ActionLink(@Model.Title, "Product", "Catalog", new { seName = @Model.SeName }, null)<br />
        @*@Html.DisplayFor(m => m.Title)<br />*@ By: @Html.DisplayFor(m => m.Author)<br />
        Published date: @Html.DisplayFor(m => m.PublishedDate)<br />
        Format: @Html.DisplayFor(m => m.Format)
    </td>
    <td>
        <p class="onlinePrice">
            <em>@Html.DisplayFor(m => m.PriceWithDiscount)</em></p>
        <p class="saving">
            <em>@Html.DisplayFor(m => m.PriceDiscount)</em></p>
        <p class="rrp">
            RRP: <em>@Html.DisplayFor(m => m.Price)</em></p>
    </td>
    <td>
        @using (Html.BeginForm("UpdateCart", "CustomCart"))
        { 
            string test = Model.Isbn13;
            int QuantTest = Model.Qty;

            @Html.EditorFor(m => Model.Qty)
            @Html.HiddenFor(m => m.Isbn13)
            //@Html.TextBoxFor(m => m.Qty)
            <input type="submit" value="Update" />
        }
    </td>
    <td>
        <p class="subTotal numeric-right">@Html.DisplayFor(m => m.Total)</p>
    </td>
</tr>

My Controller Action:

[HttpPost]
public ActionResult UpdateCart(CustomOrderLine model)
{

    //add code here


    return XXX;
}

Here's the generated HTML using the foreach loop:

<table class="order-table order-table-nomargin order-table-noborder hidden-xs hidden-sm">
<thead>
<tr><th>Products</th><th></th><th>Price</th><th>Qty.</th><th>Total</th></tr>
</thead>
<tbody>
<tr>
    <td>
        <img alt="book image" src="http://media.harrypotter.bloomsbury.com/rep/s/9781408855652_309039.jpeg"  width="100" />
    </td>
    <td>
        <a href="/uk/harry-potter-and-the-philosophers-stone-9780747558194-9781408855652">Harry Potter and the Philosopher&#39;s Stone </a><br />
         By: J.K. Rowling<br />
        Published date: 01-09-2014<br />
        Format: Paperback
    </td>
    <td>
        <p class="onlinePrice">
            <em>6.29</em></p>
        <p class="saving">
            <em>Save ВЈ0.70 (10%)</em></p>
        <p class="rrp">
            RRP: <em>6.99</em></p>
    </td>
    <td>

<form action="/CustomCart/UpdateCart" method="post">
<input class="text-box single-line" data-val="true" data-val-number="The field Qty must be a number." data-val-required="&amp;#39;Qty&amp;#39; must not be empty." id="ol_Qty" name="ol.Qty" type="text" value="1" />
<input id="ol_Isbn13" name="ol.Isbn13" type="hidden" value="9781408855652" />            
<input type="submit" name="123" id="123" value="Update 2" />
</form>    </td>
    <td>
        <p class="subTotal numeric-right">6.29</p>
    </td>
</tr>
</tbody>
</table> 
3
  • Can you show what things looked like when you were using a for loop? And can you show what the POSTed data looks like when you submit the form? Commented Jul 14, 2015 at 14:44
  • sure - I'll add to the post above... give me 2 mins. Commented Jul 14, 2015 at 14:48
  • @StriplingWarrior - just added the generated HTML. - ignore that - I've added the foreach loop!!! 2 minst... Commented Jul 14, 2015 at 14:57

2 Answers 2

3

First of all, if you want multiple CustomOrderLines to be received in your controller action, you're going to need to take a list of items. In this case, it seem like it's probably more appropriate to take the Cart, which has a list of CustomOrderLines on it:

[HttpPost]
public ActionResult UpdateCart(Cart cart)
{
    //add code here
    return XXX;
}

MVC model binding populates lists from parameters that look like this:

cart.OrderLines[0].ItemId = 123
cart.OrderLines[0].Qty = 1
cart.OrderLines[1].ItemId = 456
cart.OrderLines[1].Qty = 2

So in order for the name attributes of your HTML inputs to match this pattern, EditorFor needs to be given an expression that will help it know how to construct this name:

@for (int i=0; i<Model.Cart.OrderLines.Length; i++)
{    
  @Html.EditorFor(m => m.Cart.OrderLines[i])
}  

You'll notice that I'm using EditorFor, since it appears that you're showing an editable version of your orders. If you do this, you will want to move your display template into the location for editor templates instead.

Sign up to request clarification or add additional context in comments.

1 Comment

Perfect - got it working passing the entire cart to the Action - not exactly what I was going for but I can totally work with this - thanks for your help.
1

If you want to keep single line updates, change your controller action signature to:

[HttpPost]
public ActionResult UpdateCart(CustomOrderLine ol)
{
    return XXX;
}

This will match the prefix that is being rendered in the DisplayFor(m => ol).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.