Saving multiple objects from MVC view

后端 未结 3 1984
失恋的感觉
失恋的感觉 2020-12-17 05:58

I\'m writing my first MVC3 application which is a simple order tracking application. I would like to edit the order and the details at the same time. When I edit the order t

相关标签:
3条回答
  • 2020-12-17 06:03

    The issue that you are facing is related to the names generated by the ICollection<T> controls. Here is a detailed discussion by Phil Haack and a solution by him (in terms of an @Html extension method; download the sample project from the link given at the end of his blog post). This post targets MVC/MVC2; however it is still applicable with MVC3.

    Alternatively if you don't want to follow the hack, you can opt for a EditorTemplate for your OrderLine entity model.

    Here are the steps.

    1) Create Editor template under (Views ->Shared -> EditorTemplates -> OrderLine.cshtml) It is important to create a folder named EditorTemplates under Shared, and the template name should be same as the EntityModel for which you want to create the templete; hence the name OrderLine.cshtml)

    enter image description here

    2) Code for OrderLine.cshtml

    @model OrderTracker.Models.OrderLine
    @{
        Layout = null;
    }
    
    <!DOCTYPE html>
    @Html.HiddenFor(modelItem => Model.id)
    <tr>
    <td>
        @Html.EditorFor(modelItem => Model.Description)
    </td> 
    <td>
        @Html.EditorFor(modelItem => Model.Quantity)
    </td> 
    <td>
        @Html.EditorFor(modelItem => Model.Weight)
    </td> 
    <td>
        @Html.EditorFor(modelItem => Model.Price)
    </td>
    </tr>
    

    3) Edit your View with this code (note that I've used EditorFor for OrderLines collection)

    @model OrderTracker.Models.Order
    
    @{
        ViewBag.Title = "Edit";
    }
    
    <h2>Edit</h2>
    
    @using (Html.BeginForm())
    {
        <fieldset>
            <legend>Order</legend>   
    
            @Html.HiddenFor(model => model.ID)
            @Html.HiddenFor(model => model.UserId)
    
            <div>
                @Html.LabelFor(model => model.OrderDate)
            </div>
            <div>
                @Html.EditorFor(model => model.OrderDate)
            </div>
            <div>
                @Html.LabelFor(model => model.Description)
            </div>
            <div>
                @Html.EditorFor(model => model.Description)
            </div>                     
            <div>
            <table>
                <tr>
                    <th>
                        Description
                    </th>
                    <th>
                        Quantity
                    </th>
                    <th>
                        Weight
                    </th>
                    <th>
                        Price
                    </th>
                </tr>
                @Html.EditorFor(model => model.OrderLines)
                </table>
            </div>
            <p>
                <input type="submit" value="Save" />
            </p> 
    
        </fieldset>    
    }
    

    4) Now on post back you will see the values

    enter image description here

    0 讨论(0)
  • 2020-12-17 06:06

    The issue is with your foreach if you look at the raw html that it produces it will not be generating unique ids for each of the order lines and thus will not be able to bind the model when the form is posted back.

    Change the foreach to a for loop and then reference each orderline using the index. This will allow for unique ids to be generated in the form and allow you to bind the to the model when it is posted back.

    e.g.

    @for (var counter = 0; counter < Model.OrderLines.Count(); counter++)
    
        { 
            <tr>
                <td>
                    @Html.EditorFor(modelItem => Model.OrderLines[counter].Description)
                </td> 
                <td>
                    @Html.EditorFor(modelItem => Model.OrderLines[counter].Quantity)
                </td> 
                <td>
                    @Html.EditorFor(modelItem => Model.OrderLines[counter].Weight)
                </td> 
                <td>
                    @Html.EditorFor(modelItem => Model.OrderLines[counter].Price)
                </td>
            </tr>
        }
        </table>
    
    0 讨论(0)
  • 2020-12-17 06:10

    Using MVC it should be rather straight forward as the framework is designed to to turn a form into a model.

    [HttpGet]
    public ActionResult Edit(int id)
    {
        // (you can probably rewrite this using a lambda
        var orderWithLines = from o in db.Orders.Include("OrderLines")
                             select o;
    
        // Use ViewData rather than passing in the object in the View() method.
        ViewData.Model = orderWithLines.FirstOrDefault(x => x.ID = id);
        return View();
    }
    
    [HttpPost]
    public ActionResult Edit(OrderTracker.Models.Order model)
    {
        if (ModelState.IsValid)
        {
            // call the service layer / repository / db to persist the object graph
            _service.Save(model); // this assumes your view models are the same as your domain
        }
    }
    
    0 讨论(0)
提交回复
热议问题