How to take multiple value for strongly typed data model list in ASP.NET-MVC-5 inside razor code

697 Views Asked by At

I have strongly typed view model and I need to take multiple records for "List" from user for strongly typed list. I am struggling to achieve this in razor code. This is [httpget] method.

View Model

public class AccommodationApplicationViewModel
{
    public AccommodationApplicationViewModel() 
    {
        _RentingApplicationModel = new PropertyRentingApplication();
        _PropertyRentingPriceModel = new List<PropertyRentingPrice>();
        _AdditionalTenantModel = new List<AdditionalTenant>();
        _StudentLimitedInfoModel = new List<StudentLimitedInfo>();
    }

    public PropertyRentingApplication _RentingApplicationModel { get; set; }

    public List<PropertyRentingPrice> _PropertyRentingPriceModel { get; set; }
    public List<AdditionalTenant> _AdditionalTenantModel { get; set; }
    public List<StudentLimitedInfo> _StudentLimitedInfoModel { get; set; }

}

Razor code

<div>
    <div class="form-group">
        @Html.LabelFor(model => model._StudentLimitedInfoModel[0].StudentNumber_UWLID, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            //@Html.EditorFor(model => model._StudentLimitedInfoModel[0].StudentNumber_UWLID, new { htmlAttributes = new { @class = "form-control", @readonly = "readonly" } })
            @Html.ValidationMessageFor(model => model._StudentLimitedInfoModel[0].StudentNumber_UWLID, "", new { @class = "text-danger" })*@
        </div>
    </div>

I get error in following line

@Html.EditorFor(model => model._StudentLimitedInfoModel[0].StudentNumber_UWLID, new { htmlAttributes = new { @class = "form-control", @readonly = "readonly" } })

The error is:

Index was out of range. Must be non-negative and less than the size of the collection. Parameter name: index

2

There are 2 best solutions below

0
Chris Pratt On

You can take one of two approaches with this. If there's a fixed number of items for the list, you can simply initialize it with the appropriate number of instances. For example:

_PropertyRentingPriceModel = new List<PropertyRentingPrice>
{
    new PropertyRentingPrice(),
    new PropertyRentingPrice(),
    new PropertyRentingPrice()
};

That would give you three items. Then, in your view:

@for (var i = 0; i < Model._PropertyRentingPriceModel.Count(); i++)
{
    @Html.EditorFor(m => m._PropertyRentingPriceModel[i].Foo)
}

If the items are more fluid, or the user needs to be able to add or remove items at will, you'll need a JavaScript solution, which will involve creating the inputs and assigning them the appropriate names manually. For this, I'd recommend using some sort of data binding library with support for templates, such as Knockout or Angular. Doing so will make your life much easier. When building your JavaScript template, you just need to keep in mind the convention for collection input names that the modelbinder will expect to see in your POST request: CollectionProperty[Index].Property. For example, you input would need to look something like:

<input type="text" name="_PropertyRentingPriceModel[0].Foo" value="" />
0
Nick Albrecht On

I had to do something similar and ended up using an article I found here to do it. I'd post my implementation but I had to customize it enough that it would just confuse what you're looking for.