Alex Rivera | Logout

Model Binding on Multiple Model Form Submission from Strongly-Typed View

Asked 2009-06-30T17:39:19.367
10

I'm having problems binding on a form with multiple models being submitted. I have a complaint form which includes complaint info as well as one-to-many complainants. I'm trying to submit the form but I'm getting errors on the bind. ModelState.IsValid always returns false.

If I debug and view the ModelState Errors, I get one saying: "The EntityCollection has already been initialized. The InitializeRelatedCollection method should only be called to initialize a new EntityCollection during deserialization of an object graph".

Also, when debugging, I can see that the the Complaint Model does get populated with Complainants from the form submission, so it seems that part is working.

I'm not sure if what I'm doing is not possible with the default ModelBinder, or if I'm simply not going about it the right way. I can't seem to find any concrete examples or documentation on this. A very similar problem can be found on stackoverflow here but it doesn't seem to deal with strongly typed views.

Controller Code:

    public ActionResult Edit(int id)
    {
        var complaint = (from c in _entities.ComplaintSet.Include("Complainants")
                     where c.Id == id
                     select c).FirstOrDefault();

        return View(complaint);
    }

    //
    // POST: /Home/Edit/5
    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Edit(Complaint complaint)
    {
        if (!ModelState.IsValid)
        {
            return View();
        }
        try
        {
            var originalComplaint = (from c in _entities.ComplaintSet.Include("Complainants")
                                     where c.Id == complaint.Id
                                     select c).FirstOrDefault();
            _entities.ApplyPropertyChanges(originalComplaint.EntityKey.EntitySetName, complaint);
            _entit
Edit
Report

1 Answer

1

I worked around the ModelBinding exception by doing the following:

// Remove the error from ModelState which will have the same name as the collection.
ModelState.Remove("Complaints"/*EntityCollection*/); 
if (ModelState.IsValid) // Still catches other errors.
{
    entities.SaveChanges(); // Your ObjectContext
}

The main drawback is that the exception is still thrown and that can be expensive at runtime. The elegant work around may be to create a wrapper around the existing DefaultBinder and prevent it from instantiating the EntityCollection again, which is already done by EF. Then binding that collection to the form values (FormCollection).

Keep in mind if you're binding more than one collection, you will need to remove the error for each collection.

In my experiment, the collection saved successfully as well as the root object in the graph which the collection was part of.

Hope that helps someone else.

answered 2009-10-01T02:42:49.470

Your Answer