Search code examples
c#asp.net-mvcasp.net-mvc-4razoreditorfor

MVC Razor EditorFor Last Object in List


I'm trying to display EditorFor for the last child Object in an collection. Below are the POCOs for the Order (Parent) and Hold (child collection):

public class Order
{
    public int ID {get;set;}
    public string Name {get;set;}
    ....
    public virtual List<Hold> Holds { get; set; }
}

public class Hold
{
    public int ID { get; set; }
    public int OrderID { get; set; }
    public virtual Order Order { get; set; }
    public DateTime? When { get; set; }
    public string Reason { get; set; }
}

Here's my attempt at creating an Order view that shows an Order and the last Hold if there is one present. I've commented out the last Hold attempt that doesn't work.

@model Order

@using (Html.BeginForm("Update", "Order", FormMethod.Post, new {}))
{
   <div class="form-group row">
      @Html.LabelFor(x => x.Name, new { @class = "col-xs-2" })
      <div class="col-xs-10">
         @Html.EditorFor(x => x.Name, new { @class = "form-control"})
      </div>
   </div>

   <div class="form-group row">
      <label class="col-xs-2">When</label>
      <div class="col-xs-10">
         @*@Html.EditorFor(x => x.Holds.Last().When, new {})*@
      </div>
   </div>
}

The Holds collection can also be null so doing Last() in that case will case an null exception even if that did work.

This seems like something simple and I have this pattern in a couple places in my database. Can anyone recommend a good way to handle this situation?

Thanks!


Solution

  • You should use a view model for this because you wont get a very good response in your HttpPost action when you post this back

    public class OrderViewModel
    {
        public OrderViewModel()
        {
            Order = new Order();
            Hold = new Hold();
        }
        public Order Order { get; set; }
        public Hold Hold { get; set; }
    }
    
    public ActionResult Edit(int id)
    {
    
        var o = from o context.Order.Include("Holds").Single(id);
        var model = new OrderViewModel()
        {
            Order = o
        }
        if (o.Holds.Count() > 0)
            model.Hold = o.Holds.Last();
        return View(model);
    }
    

    then just use EditorFors

    @model OrderViewModel
    
    @using (Html.BeginForm("Update", "Order", FormMethod.Post, new {}))
    {
       <div class="form-group row">
          @Html.LabelFor(x => x.Order.Name, new { @class = "col-xs-2" })
          <div class="col-xs-10">
             @Html.EditorFor(x => x.Order.Name, new { @class = "form-control"})
          </div>
       </div>
    
       <div class="form-group row">
          <label class="col-xs-2>When</label>
          <div class="col-xs-10">
             @Html.EditorFor(x => x.Hold.When)
          </div>
       </div>
    }