Search code examples
asp.net-mvclistienumerablemvc-editor-templateseditorfor

EditorFor for list view error


I have a class which contains a property as a list of another object

public class MyObject {
    public MyObject()
    {
        this.Items = new List<Item>
                                {
                                    new Item(),
                                    new Item()
                                };
    }

    public List<Item> Items { get; set; }
    }
}

public class Item
{
    public double ItemSetting { get; set; }

    [CompareIf("ItemSetting", Operator.LessThanOrEqual, ErrorMessageResourceType = typeof(UiResources), ErrorMessageResourceName = "ItemMinError")]
    public double ItemMin { get; set; }
}

I'm trying to display the list in a template:

@model IEnumerable<Web.Models.Item>
@{
}

via:

@model Web.Models.MyObject
@{
    @Html.EditorFor(x => x.Items)
}

but I'm getting an error:

The model item passed into the dictionary is of type 'Web.Models.MyObject', but this dictionary requires a model item of type 'System.Collections.Generic.IEnumerable`1[Web.Models.Item]'.

I'm passing to the editor template a property which is a type of List so why does it get it as a single Item type?

In the Item template I need to display a title which tells the index of the item in the List. Eg.:

<h3>Item 1</h3>
@Html.TextBoxFor(x => x.ItemSetting })

and for next Item:

<h3>Item 2</h3>
@Html.TextBoxFor(x => x.ItemSetting })

(Remember I created 2 empty items in MyObject constructor)

so haw do I get the relevant index if I'm only displaying one item in the Item template?


Solution

  • The reason you are getting this error is because the value of your model is null (therefore model.Items is null) so by default, it passes the main model to the template. You need to ensure you pass an instance of you model to the view in the GET method.

    However your method in the main view should be

    @model Web.Models.Item
    

    not @model IEnumerable<Web.Models.Item>. The method accepts IEnumerable<T> and is smart enough to generate the html for each item in the collection based on the html in the template