gingerbreadboy
gingerbreadboy

Reputation: 7769

Rebuilding an ICollection after MVC edit?

If my model Product has a member ICollection<ProductOption> how do I rebuild my Product with the member collection in my Controller.Edit(...) method on post back from Edit?

(We can assume we never add or remove an option, only ever edit.)

Razor:

@model Models.Products.Product    
@{
    ViewBag.Title = "Edit";
    Layout = "~/Views/Shared/_GlobalLayout.cshtml";
}

@using (Html.BeginForm()) {
    @Html.ValidationSummary(true)
    <fieldset>         
    @Html.HiddenFor(model => model.Id)
    <legend>Product</legend>
    <div class="editor-label">
        @Html.LabelFor(model => model.Name)
    </div>        
    @foreach (ProductOption option in Model.Options)
    {
        <div style="border:1px solid black; margin: 5px; padding:5px 7px;">
            @Html.Partial("_ProductOptionInput", option)
        </div>
    }    
    <p>
        <input type="submit" value="Save" />
    </p>
    </fieldset>
} 

controller:

[HttpPost]
public ActionResult Edit(int id, FormCollection collection)
{           
    var p = _repository.ById(id);
    UpdateModel<Product>(p);

    _repository.SaveChanges();

    return RedirectToAction("Index");          
}

partial view:

@modelModels.Products.ProductOption

@Html.ValidationSummary(true)
<fieldset>
    <legend>ProductOption</legend>    
    @Html.HiddenFor(model => model.Id)    
    <div class="editor-label">
        @Html.LabelFor(model => model.Term)
    </div>
</fieldset>

UPDATE

My FormCollection in ActionResult Edit(int id, FormCollection collection) is essentially a dictionary, so it has the ProductOption values for one of the updated ProductOptions but not the rest of them as the keys (ie the ProductOptions property names) can't be repeated in the dictionary.

Upvotes: 2

Views: 1072

Answers (2)

gingerbreadboy
gingerbreadboy

Reputation: 7769

I added the following in the Razor view and it works like a charm!

@Html.EditorFor(model => model.Options.ToList()[0], templateName: "ProductOptionInput", htmlFieldName: "Options[0]")
@Html.EditorFor(model => model.Options.ToList()[1], templateName: "ProductOptionInput", htmlFieldName: "Options[1]")

Upvotes: 1

Brian Ball
Brian Ball

Reputation: 12596

You either need to write your own model binder (either for ICollection<ProductOption> or one that pulls your entity out of the database instead of instantiating a new instance), or you can NOT take the model in as a parameter, and instead, pull it out of the database in your action method, then call TryUpdateModel from the controller.

HTH

Upvotes: 1

Related Questions