Leron
Leron

Reputation: 9866

Model is always null when submitting form from Razor view

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.

Upvotes: 0

Views: 1672

Answers (3)

Nada N. Hantouli
Nada N. Hantouli

Reputation: 1330

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>
    }

Upvotes: 2

Oleksii Aza
Oleksii Aza

Reputation: 5398

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

Upvotes: 1

Amit
Amit

Reputation: 15387

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

Upvotes: 2

Related Questions