ASP.NET MVC 2 - Saving child entities on form submit

Posted by Justin on Stack Overflow See other posts from Stack Overflow or by Justin
Published on 2010-06-12T18:53:01Z Indexed on 2010/06/12 19:03 UTC
Read the original article Hit count: 588

Filed under:
|

Hey,

I'm using ASP.NET MVC 2 and am struggling with saving child entities. I have an existing Invoice entity (which I create on a separate form) and then I have a LogHours view that I'd like to use to save InvoiceLog's, which are child entities of Invoice. Here's the view:

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<TothSolutions.Data.Invoice>" %>

<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
    Log Hours
</asp:Content>

<asp:Content ID="Content3" ContentPlaceHolderID="HeadContent" runat="server">
    <script type="text/javascript">
        $(document).ready(function () {
            $("#InvoiceLogs_0__Description").focus();
        });
    </script>
</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">

<h2>Log Hours</h2>

<% using (Html.BeginForm("SaveHours", "Invoices")) {%>
    <%: Html.ValidationSummary(true) %>
    <fieldset>
        <legend>Fields</legend>

        <table>
            <tr>
                <th>Date</th>
                <th>Description</th>
                <th>Hours</th>
            </tr>
            <%
           int index = 0;
           foreach (var log in Model.InvoiceLogs) { 
            %>
                <tr>
                    <td><%: log.LogDate.ToShortDateString() %></td>
                    <td><%: Html.TextBox("InvoiceLogs[" + index + "].Description")%></td>
                    <td><%: Html.TextBox("InvoiceLogs[" + index + "].Hours")%></td>
                    <td>Hours</td>
                </tr>
            <% 
               index++;
           } 
           %>
        </table>

        <p>
            <%: Html.Hidden("InvoiceID") %>
            <%: Html.Hidden("CreateDate") %>
            <input type="submit" value="Save" />
        </p>
    </fieldset>
 <% } %>

<div>
    <%: Html.ActionLink("Back to List", "Index") %>
</div>

</asp:Content>

And here's the controller code:

//GET: /Secure/Invoices/LogHours/
        public ActionResult LogHours(int id)
        {
            var invoice = DataContext.InvoiceData.Get(id);
            if (invoice == null)
            {
                throw new Exception("Invoice not found with id: " + id);
            }
            return View(invoice);
        }

//POST: /Secure/Invoices/SaveHours/
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult SaveHours([Bind(Exclude = "InvoiceLogs")]Invoice invoice)
        {
            TryUpdateModel(invoice.InvoiceLogs, "InvoiceLogs");
            invoice.UpdateDate = DateTime.Now;
            invoice.DeveloperID = DeveloperID;
            //attaching existing invoice.
            DataContext.InvoiceData.Attach(invoice);
            //save changes.
            DataContext.SaveChanges();
            //redirect to invoice list.
            return RedirectToAction("Index");
        }

And the data access code:

public static void Attach(Invoice invoice)
            {
                var i = new Invoice { InvoiceID = invoice.InvoiceID };
                db.Invoices.Attach(i);
                db.Invoices.ApplyCurrentValues(invoice);
            }

In the SaveHours action, it properly sets the values of the InvoiceLog entities after I call TryUpdateModel but when it does SaveChanges it doesn't update the database with the new values. Also, if you manually update the values of the InvoiceLog entries in the database and then go to this page it doesn't populate the textboxes so it's clearly not binding correctly.

Thanks, Justin

© Stack Overflow or respective owner

Related posts about ASP.NET

Related posts about asp.net-mvc