Master-details style view in MVC 4

asp.net-mvc entity-framework

Question

I have an ASP.NET MVC 4 internet application with EF.

My model: Orders and OrderDetails: Orders and OrderDetails

My View: Order View

Q: How can I display my orderdetails records in my order view? (with or without JS?; in a webgrid or a table?)

Create.cshtml

    <div class="editor-label">
        @Html.LabelFor(model => model.OrderDate)
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => model.OrderDate)
        @Html.ValidationMessageFor(model => model.OrderDate)
    </div>

    <div class="editor-label">
        @Html.LabelFor(model => model.OrderNo)
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => model.OrderNo)
        @Html.ValidationMessageFor(model => model.OrderNo)
    </div>

    <div class="editor-label">
        @Html.LabelFor(model => model.Total)
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => model.Total)
        @Html.ValidationMessageFor(model => model.Total)
    </div>

    <div class="editor-label">
        @Html.LabelFor(model => model.Shipping)
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => model.Shipping)
        @Html.ValidationMessageFor(model => model.Shipping)
    </div>
    @*OrderDetails Part - Works only on the Edit part*@
    <table>
        <tr>
            <th>Product</th>
            <th>Unit Price</th>
            <th>Quantity</th>
            <th>Discount</th>
        </tr>
    @foreach (OrderDetails item in Model.OrderDetails.OrderBy(d=>d.Products.ProductName))
    {
        <tr>
            <td>@item.Products.ProductName</td>
            <td>@item.UnitPrice</td>
            <td>@item.Quantity</td>
            <td>@item.Discount</td>
            <td>
                @Html.ActionLink("Edit", "Edit", "OrderDetails", new { id = item.OrderDetailId }, new { }) |
                @Html.ActionLink("Details", "Details", "OrderDetails", new { id = item.OrderDetailId }, new { }) |
                @Html.ActionLink("Delete", "Delete", "OrderDetails", new { id = item.OrderDetailId }, new { })
            </td>
        </tr>  
    }
    </table>

    <p>
        <input type="submit" value="Create" />
    </p>
1
4
9/24/2012 3:17:44 PM

Popular Answer

You should be using viewmodels to achive this. You should not expose your business models directly to views. Instead use viewmodels to provide another level of abstraction.

So, do not change your models at all. Define a view model for your view. I will not be including all the fields in viewmodel.

/* Viewmodel for your Order/Create page */
public class OrderCreate
{
    /* Attributes for your order */
    public string OrderDate          { get; set; }
    public string OrderNo            { get; set; }
    public string Shipping           { get; set; }
    ....
    ....

    /* List that will contain all details */
    public IList<ProductDetail> ProductDetails      { get; set; }

}

/* Viewmodel for each of the products */ 
public class ProductDetail
{
    public string Product            { get; set; }
    public string UnitPrice          { get; set; }
    public string Quantity           { get; set; }
    ....
    ....
}

Now in your GET action, return this viewmodel to your view instead of your business model.

//
// GET: /Order/Create

public ActionResult Index()
{
    /* New viewmodel for your view */
    var viewModel = new OrderCreate();
    viewModel.ProductDetails = new List<ProductDetail>();

    /* Assuming the number of products is static */
    for(int i = 0; i < NUMBER_OF_PRODUCTS; i++)
    {
        viewModel.ProductDetails.Add( new ProductDetail() );
    }

    return View(viewModel);
}

With this viewmodel you can now access the values filled in your view. When you post back your view to post action, create your business model there using the data from viewmodel.

//
// POST: /Order/Create

[HttpPost]
public ActionResult Index(OrderCreate viewModel)
{
    if(ModelState.IsValid))
    {
        var model = new Order();

        //TODO: Populate model through viewmodel, loop viewModel.ProductDetails

        return RedirectToAction("Index");
    }

    // Model is not valid
    return View(viewMode);
}

Some advices, if you become bored with mapping your viewmodels to actual models, try AutoMapper

Hope it helps.

3
9/22/2012 1:02:54 PM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow