MVC Multiple tables one model

MichaelMcCabe picture MichaelMcCabe · Oct 12, 2013 · Viewed 13.6k times · Source

I am having difficulty with my understanding of MVC coming from an aspx world.

I have a Model called CustomerGarment. This has a Order and a Customer along with a few garments.

public class CustomerGarment
{
    public int CustomerGarmentId { get; set; }

    public virtual Customer Customer { get; set; }

    public virtual Order Order { get; set; }

    public virtual GarmentJacket GarmentJacket { get; set; }
    public virtual GarmentShirt GarmentShirt { get; set; }
}

I have a method for get and post. When the page loads, it creates a new CustomerGarment instance and querys the database to fill the Customer and Order variables. I then use the viewbag to show on the screen a list of GarmentJackets and GarmentShirts

The page then views and using the view I can access the model perfectly. Drop downs load with the viewbag contents and I can access all Customer and Order variables using the model I have passed.

The problem I then face is when I use the HttpPost. The model is not passed back with the information I passed to it.

    public ActionResult AddGarments(int orderId, int customerId)
    {
        CustomerGarment cg = new CustomerGarment();
        cg.Order = (from a in db.Orders where a.OrderId == orderId select a).FirstOrDefault();
        cg.Customer = (from a in db.Customers where a.CustomerId == customerId select a).FirstOrDefault();

        var jackets = from a in db.GarmentJackets orderby a.Type, a.SleeveLengthInches, a.ChestSizeInches select a;
        var shirts= from a in db.GarmentKilts orderby a.PrimarySize, a.DropLength select a;
        ViewBag.GarmentJacket = new SelectList(jackets, "GarmentJacketId", "GarmentJacketId");
        ViewBag.GarmentShirt = new SelectList(shirts, "GarmentShirtId", "GarmentShirtId");

        return View(cg);
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult AddGarments(CustomerGarment cg)
    {
        // Here, I do not have the customer info for example
        db.CustomerGarments.Add(cg);
        db.SaveChanges();
        return RedirectToAction("Index");

        return View(cg);
    }

This is a bit of my view

@Html.HiddenFor(model => model.Order.OrderId)
    @Html.HiddenFor(model => model.Order.CustomerId)

    <div class="display-field">
        @Html.DisplayFor(model => model.Customer.Name)
    </div>


    <div class="editor-label">
        @Html.LabelFor(model => model.GarmentJacket, "Jacket")
    </div>
    <div class="editor-field">
        @Html.DropDownListFor(m => m.GarmentJacket, (SelectList)ViewBag.GarmentJacket, new {style="width:312px;height:30px;margin-top:2px;margin-bottom:5px"})
    </div>

EDIT

My Garment Jacket Model

public class GarmentJacket : Garment
{
    public int GarmentJacketId { get; set; }

    [Required]
    public string Type { get; set; }

    [Required]
    [Display(Name = "Chest Size")]
    public int ChestSizeInches { get; set; }

    [Required]
    [Display(Name = "Sleeve Length")]
    public int SleeveLengthInches { get; set; }
 }

public class Garment
{
    [DataType(DataType.Date)]
    public DateTime? DateRetired { get; set; }

    [Required]
    public string Barcode { get; set; }

    [Required]
    public bool Adults { get; set; }
}

Answer

ataravati picture ataravati · Oct 12, 2013

In your CustomerGarment class, you should have:

public class CustomerGarment
{
    public int CustomerGarmentId { get; set; }
    public int CustomerId { get; set; }
    public int OrderId { get; set; }
    public int GarmentJacketId { get; set; }
    public int GarmentShirtId { get; set; }

    public virtual Customer Customer { get; set; }
    public virtual Order Order { get; set; }
    public virtual GarmentJacket GarmentJacket { get; set; }
    public virtual GarmentShirt GarmentShirt { get; set; }
}

And, then, in your View, your DropDownList will look like:

@Html.DropDownListFor(m => m.GarmentJacketId, (SelectList)ViewBag.GarmentJacket, new {style="width:312px;height:30px;margin-top:2px;margin-bottom:5px"})

Your DropDownList only posts one value, which is the GarmentJacketId. You can't bind that Id to the whole GarmentJacket class.

By the way, you also need to replace your hidden inputs with these:

@Html.HiddenFor(model => model.OrderId)
@Html.HiddenFor(model => model.CustomerId)