0

I'm working on an ASP.NET MVC 4 application. I have a view called Currencty.cshtml and tow methods in my controller:

    [HttpGet]
    public ActionResult Currency()
    {
        IEnumerable<Currency> model = unitOfWork.CurrencyRepository.GetAll();
        return View(model);
    }

    [HttpPost]
    public ActionResult Currency(IEnumerable<Currency> model)
    {
        var test = model;

The view itself is :

@model IEnumerable<MyProject.Models.Currency>
@using (Html.BeginForm(new { ReturnUrl = ViewBag.ReturnUrl }))
{
    @Html.AntiForgeryToken()
    @Html.ValidationSummary(true)
<table>
   <thead>
     <tr>
         <th rowspan="2">Code</th>
         <th rowspan="2">Currency</th>
         <th rowspan="2">Fixing</th>
         <th colspan="2">PayDesk</th>
         <th colspan="2">NoDesk</th>
     </tr>
     <tr>
         <th>Buy</th>
         <th>Sell</th>
         <th>Buy</th>
         <th>Sell</th>
     </tr>
   </thead>
   <tbody>
     @foreach (var item in Model)
     { 
        <tr>
            <td>@Html.HiddenFor(modelItem => item.CurrencyID)
                @Html.TextBoxFor(modelItem => item.Code)</td>
            <td>@Html.TextBoxFor(modelItem => item.CurrencyName)</td>
            <td>@Html.TextBoxFor(modelItem => item.FixingRate)</td>
            <td>@Html.TextBoxFor(modelItem => item.PayDeskBuy)</td>
            <td>@Html.TextBoxFor(modelItem => item.PayDeskSell)</td>
            <td>@Html.TextBoxFor(modelItem => item.NoDeskBuy)</td>
            <td>@Html.TextBoxFor(modelItem => item.NoDeskSell)</td>
        </tr>
     }
    </tbody>

</table>
    <input type="submit" id="form-submit-button" value="Save" />
}

The problem is that I have a breakpoint in [HttpPost] public ActionResult Currency(IEnumerable<Currency> model) and I can see that when I submit the form I get there, but the model is always null. Everything seems so straight-forward I just can't see what's going wrong so that I can't get my data back. When I load the form with the [HttpGet] method everything is OK and I see the data.

Leron
  • 9,546
  • 35
  • 156
  • 257

3 Answers3

2

Try to bind with for loop instead of foreach

@for(int i=0;i<Model.Count;i++)
    {
        <td>@Html.HiddenFor(modelItem => Model[i].CurrencyID)
                @Html.TextBoxFor(modelItem => Model[i].Code)</td>
            <td>@Html.TextBoxFor(modelItem => Model[i].CurrencyName)</td>
            <td>@Html.TextBoxFor(modelItem => Model[i].FixingRate)</td>
            <td>@Html.TextBoxFor(modelItem => Model[i].PayDeskBuy)</td>
            <td>@Html.TextBoxFor(modelItem => Model[i].PayDeskSell)</td>
            <td>@Html.TextBoxFor(modelItem => Model[i].NoDeskBuy)</td>
            <td>@Html.TextBoxFor(modelItem => Model[i].NoDeskSell)</td>
    }

Reference

Community
  • 1
  • 1
Amit
  • 15,217
  • 8
  • 46
  • 68
  • It seams like a trivial thing, yet it's hard to understand where the difference in the two loops comes from. +1 for the reference, which actually sheds some light on why the `for` loop works, and not just a "this works" or "try this" answer. – Andrei V Dec 02 '13 at 11:47
  • Cannot apply indexing with [] to an expression of type 'System.Collections.Generic.IEnumerable' any idea? – Leron Dec 02 '13 at 11:47
  • 1
    I couldn't make it work with `IEnumerable`. I'm not sure why - just changing to `List` didn't worked either I had to use both - `List` and `@for()` in order to get it working. In your current example I get an error for using `<` in `i – Leron Dec 02 '13 at 12:00
2

To be able to list all values of a list of objects and be able to submit all of them to a POST action I faced a strange problem that I always had a null submitted to the POST action. So, I changed the IEnumerable<> list on top of the razor view page- this page to List<> and I didn't use the @foreach(), I instead used the @for() with indexing

@for (int i = 0; i < Model.Count(); i++)
    {
    <tr>
        <td>@Html.DisplayFor(modelItem => Model[i].UserId)</td>
        @Html.HiddenFor(modelItem => Model[i].UserId)
        <td>@Html.CheckBoxFor(modelItem => Model[i].isLead)</td>
    </tr>
    }
Amalea
  • 526
  • 1
  • 6
  • 17
Nada N. Hantouli
  • 1,310
  • 1
  • 12
  • 20
1

Try to use for loop and indexers on model:

@for(int i=0;i<Model.Count();i++)
    {
        <td>@Html.HiddenFor(modelItem => item.CurrencyID)
                @Html.TextBoxFor(modelItem => Model[i].Code)</td>
            <td>@Html.TextBoxFor(modelItem => Model[i].CurrencyName)</td>
            <td>@Html.TextBoxFor(modelItem => Model[i].FixingRate)</td>
            <td>@Html.TextBoxFor(modelItem => Model[i].PayDeskBuy)</td>
            <td>@Html.TextBoxFor(modelItem => Model[i].PayDeskSell)</td>
            <td>@Html.TextBoxFor(modelItem => Model[i].NoDeskBuy)</td>
            <td>@Html.TextBoxFor(modelItem => Model[i].NoDeskSell)</td>
    }

Also in order to apply indexers you should pass List as model. So in your action:

[HttpGet]
public ActionResult Currency()
{
    var model = unitOfWork.CurrencyRepository.GetAll().ToList();
    return View(model);
}

And in your view:

@model List<MyProject.Models.Currency>

If you want more detailed information about list binding I recomend you to read these articles:

Model Binding To A List by Phill Haacked

ASP.NET Wire Format for Model Binding to Arrays, Lists, Collections, Dictionaries by S. Hanselman

Oleksii Aza
  • 5,368
  • 28
  • 35