I have two POCO classes a User and an Address. Address is a complex object, and a User has one Address. I want to create a single User view that allows the create/edit of an Address on the same form via MVC Scaffolding + Entity Framework + Repository Pattern. The Create User View works correctly, but when I try to make changes to the Address in the User Edit View, the changes don’t get propagated. How do I force the changes to propogated down to the Address object from the User View? Everything else is auto generated.
POCO Classes
public class TestDB : DbContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
}
public DbSet<Address> Addresses { get; set; }
public DbSet<User> Users { get; set; }
}
public class Address
{
public int ID { get; set; }
public string Street1 { get; set; }
public string Street2 { get; set; }
public string City { get; set; }
public string State { get; set; }
public string PostalCode { get; set; }
public string Country { get; set; }
}
public class User
{
public int ID { get; set; }
public string UserName { get; set; }
/*[ForeignKey("Address")]
public int AddressID { get; set; }*/
public virtual Address Address { get; set; }
}
Edit User View
<% using (Html.BeginForm()) { %>
<%: Html.ValidationSummary(true) %>
<fieldset>
<legend>User</legend>
<%: Html.HiddenFor(model => model.ID) %>
<%: Html.Partial("CreateOrEdit", Model) %>
<legend>Address</legend>
<div class="editor-label">
<%: Html.LabelFor(model => model.Address.Street1) %>
</div>
<div class="editor-field">
<%: Html.EditorFor(model => model.Address.Street1)%>
<%: Html.ValidationMessageFor(model => model.Address.Street1)%>
</div>
<div class="editor-label">
<%: Html.LabelFor(model => model.Address.Street2)%>
</div>
<div class="editor-field">
<%: Html.EditorFor(model => model.Address.Street2)%>
<%: Html.ValidationMessageFor(model => model.Address.Street2)%>
</div>
<div class="editor-label">
<%: Html.LabelFor(model => model.Address.City)%>
</div>
<div class="editor-field">
<%: Html.EditorFor(model => model.Address.City)%>
<%: Html.ValidationMessageFor(model => model.Address.City)%>
</div>
<div class="editor-label">
<%: Html.LabelFor(model => model.Address.State)%>
</div>
<div class="editor-field">
<%: Html.EditorFor(model => model.Address.State)%>
<%: Html.ValidationMessageFor(model => model.Address.State)%>
</div>
<div class="editor-label">
<%: Html.LabelFor(model => model.Address.PostalCode)%>
</div>
<div class="editor-field">
<%: Html.EditorFor(model => model.Address.PostalCode)%>
<%: Html.ValidationMessageFor(model => model.Address.PostalCode)%>
</div>
<div class="editor-label">
<%: Html.LabelFor(model => model.Address.Country)%>
</div>
<div class="editor-field">
<%: Html.EditorFor(model => model.Address.Country)%>
<%: Html.ValidationMessageFor(model => model.Address.Country)%>
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
<% } %>
<div>
<%: Html.ActionLink("Back to List", "Index") %>
</div>
Editor Template for Address:
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<AddressTest.Models.Address>" %>
<script src="<%: Url.Content("~/Scripts/jquery-1.5.1.min.js") %>" type="text/javascript"></script>
<script src="<%: Url.Content("~/Scripts/jquery.validate.min.js") %>" type="text/javascript"></script>
<script src="<%: Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js") %>" type="text/javascript"></script>
<% using (Html.BeginForm()) { %>
<%: Html.ValidationSummary(true) %>
<fieldset>
<legend>Address</legend>
<%: Html.HiddenFor(model => model.ID) %>
<div class="editor-label">
<%: Html.LabelFor(model => model.Street1) %>
</div>
<div class="editor-field">
<%: Html.EditorFor(model => model.Street1) %>
<%: Html.ValidationMessageFor(model => model.Street1) %>
</div>
<div class="editor-label">
<%: Html.LabelFor(model => model.Street2) %>
</div>
<div class="editor-field">
<%: Html.EditorFor(model => model.Street2) %>
<%: Html.ValidationMessageFor(model => model.Street2) %>
</div>
<div class="editor-label">
<%: Html.LabelFor(model => model.City) %>
</div>
<div class="editor-field">
<%: Html.EditorFor(model => model.City) %>
<%: Html.ValidationMessageFor(model => model.City) %>
</div>
<div class="editor-label">
<%: Html.LabelFor(model => model.State) %>
</div>
<div class="editor-field">
<%: Html.EditorFor(model => model.State) %>
<%: Html.ValidationMessageFor(model => model.State) %>
</div>
<div class="editor-label">
<%: Html.LabelFor(model => model.PostalCode) %>
</div>
<div class="editor-field">
<%: Html.EditorFor(model => model.PostalCode) %>
<%: Html.ValidationMessageFor(model => model.PostalCode) %>
</div>
<div class="editor-label">
<%: Html.LabelFor(model => model.Country) %>
</div>
<div class="editor-field">
<%: Html.EditorFor(model => model.Country) %>
<%: Html.ValidationMessageFor(model => model.Country) %>
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
<% } %>
<div>
<%: Html.ActionLink("Back to List", "Index") %>
</div>
Change to User Edit View:
<% using (Html.BeginForm()) { %>
<%: Html.ValidationSummary(true) %>
<fieldset>
<legend>User</legend>
<%: Html.HiddenFor(model => model.ID) %>
<%: Html.Partial("CreateOrEdit", Model) %>
<%: Html.Editor("Address", Model.Address) %>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
<% } %>
The solution was to modify the User Update Repository Method and mark the entity state modified for the Address. I also needed to add a hidden property for the Address.ID on the User Edit View.
User Insert/Update Repository Method
Additional Hidden Property on User Edit View
Controller Edit Action