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 the ActionResult for the Edit returns the order and the associated line (i'm using EF as well).
public ActionResult Edit(int id)
{
// Get the order with the order lines
var orderWithLines = from o in db.Orders.Include("OrderLines")
where o.ID == id
select o;
// Not sure if this is the best way to do this.
// Need to find a way to cast to "Order" type
List<Order> orderList = orderWithLines.ToList();
Order order = orderList[0];
// Use ViewData rather than passing in the object in the View() method.
ViewData.Model = order;
return View();
}
The order and the lines display with no issue but when I save the page I do not get any of the lines passed back to the controller. Only the order. Here is the View code.
@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>
<table>
<tr>
<th>
Description
</th>
<th>
Quantity
</th>
<th>
Weight
</th>
<th>
Price
</th>
<th></th>
</tr>
@foreach (var line in Model.OrderLines)
{
<tr>
<td>
@Html.EditorFor(modelItem => line.Description)
</td>
<td>
@Html.EditorFor(modelItem => line.Quantity)
</td>
<td>
@Html.EditorFor(modelItem => line.Weight)
</td>
<td>
@Html.EditorFor(modelItem => line.Price)
</td>
</tr>
}
</table>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
Can I please get some guidance on the best way to save the line data as well as the order data.
Thanks.
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)

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

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With