Search code examples
asp.net-mvc-3postrazorgetactionmethod

Empty Enumeration in post method


I have this view

@model IEnumerable<ViewModelRound2>

... <snip> ...

@{
    using (Html.BeginForm(new { round1Ring3Bids = Model }))
    {
        if (Model != null && Model.Count() > 0)
        {
                ... <snip> ...

                @for (var x = 0; x < Model.Count(); x++)
                {
                    ViewModelRound2 viewModelRound2 = Model.ElementAt(x);
                    Bid bid = viewModelRound2.Bid;

                    string userName = @bid.User.Invitation.Where(i => i.AuctionId == bid.Lot.Lot_Auction_ID).First().User.User_Username;

                    <tr>
                        <td>
                            @userName
                        </td>
                        <td>
                            @bid.Bid_Value
                        </td>
                        <td>
                            @Html.EditorFor(c => c.ElementAt(x).SelectedForRound2) 
                        </td>
                    </tr>
                }

            </table>

            <div class="buttonwrapper2">
                <input type="submit" value="Select"/>              
            </div>
        }
    }
}

I have a post method that this goes to when the submit button is hit

[HttpPost]
        public ActionResult Round2Manager(IEnumerable<ViewModelRound2> round1Ring3Bids)

Problem is that the enumeration is always empty. Why is this?


Solution

  • Problem is that the enumeration is always empty. Why is this?

    Because you are not respecting the wire format that the default model binder expects to bind collections.

    The following:

    @Html.EditorFor(c => c.ElementAt(x).SelectedForRound2) 
    

    generates absolutely wrong names for your input fields.

    I would recommend you using editor templates to avoid those kind of problems:

    @model IEnumerable<ViewModelRound2>
    
    @using (Html.BeginForm())
    {
        if (Model != null && Model.Count() > 0)
        {
            <table>
                @Html.EditorForModel()
            </table>
            <div class="buttonwrapper2">
                <input type="submit" value="Select"/>              
            </div>
        }
    }
    

    and then define a custom editor template for the ViewModelRound2 type (~/View/Shared/EditorTemplates/ViewModelRound2.cshtml) which will automatically be rendered for each element of this collection:

    @model ViewModelRound2
    @ {
        string userName = Model.Bid.User.Invitation.Where(
            i => i.AuctionId == Model.Bid.Lot.Lot_Auction_ID
        ).First().User.User_Username;
    }
    
    <tr>
        <td>
            @userName
        </td>
        <td>
            @Model.Bid.Bid_Value
        </td>
        <td>
            @Html.EditorFor(c => c.SelectedForRound2) 
        </td>
    </tr>
    

    You will now notice how the text input fields have correct names:

    name="[0].SelectedForRound2"
    name="[1].SelectedForRound2"
    name="[2].SelectedForRound2"
    ...
    

    Compare this with your initial values.