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.

3 Answers 3

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

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

3 Comments

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.
Cannot apply indexing with [] to an expression of type 'System.Collections.Generic.IEnumerable<MyProject.Models.Currency>' any idea?
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<Model.Count. I've closed the page with the original error by mistake but it was complaining about using < with int and nested... dunno
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>
    }

Comments

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

4 Comments

Cannot apply indexing with [] to an expression of type 'System.Collections.Generic.IEnumerable<MyProject.Models.Currency>' any idea?
@Leron, you can always set Model.ToList().
try return View(model.toList()) in Http Get method
Yeah, you were right. Not working until change it to List. Your example is OK.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.