Model binding to Lists throws "Collection is read-only" exception

Viewed 11130

I have a class like this:

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

    public SomeModel()
    {
        this.Items = new List<Item>();
    }

}

Where there can be a variable amount of Items upon form post, zero to many. I'm using javascript to dynamically append hidden input fields on submit:

$("#container").children(".item").each(function (i) {
    form.append('<input type="hidden" name="Items[' + i + '].Id" value="' + $(this).val() + '" />');
});

However, after submitting, I get this error:

System.NotSupportedException: Collection is read-only.

The rendered syntax is basically the same as one I would get using @Html.HiddenFor(model => model.Items[i].Id) with model.Items being an array instead of a list, and that works fine. What is going wrong here?

Action Method signature:

public ActionResult Post(SomeModel m)
{
4 Answers

MVC Model Binder should work with arrays, so replacing with a List is a workaround, but not the right solution.

I had the same problem, but it happens to me only sometimes. So I did not understand why this issue takes place. Then I discovered something that I think is worhty to share: the problem was in the javascript code.

Here my scenario:

I have a model where I use one array

public class SomeModel
{
    public Item[] Items { get; set; }

    public SomeModel()
    {
        this.Items = new Item[3] {0, 0, 0};
    }
}

I found the solution just changing the javascript that I use to call the web method!

-> case A - It throws the exception "Collection is read only"

$.ajax({
        type: "POST",
        async: true,
        url: myUrl,
        data: JSON.stringify(myData),
        contentType: "application/json; charset=utf-8",
        dataType: "html"
    })

-> case B - It works without any exception!

$.ajax({
        type: "POST",
        async: true,
        url: myUrl,
        data: myData,
        dataType: "html"
    })

Actually MVC model binding should works with array, so replacing with a List was not the answer I was looking for.

Good coding.

Related