Распространение изменений на вложенные объекты в MVC 3 - PullRequest
0 голосов
/ 21 июля 2011

У меня есть два класса POCO: пользователь и адрес.Адрес является сложным объектом, и у пользователя есть один адрес.Я хочу создать одно представление пользователя, которое позволяет создавать / редактировать адрес в той же форме через MVC Scaffolding + Entity Framework + Repository Pattern.Создание представления пользователя работает правильно, но когда я пытаюсь внести изменения в адрес в представлении редактирования пользователя, изменения не распространяются.Как заставить изменения распространяться на объект Address из представления пользователя?Все остальное генерируется автоматически.

Классы POCO

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; }
}

Редактирование представления пользователя

<% 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>

Шаблон редактора для адреса:

<%@ 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>

Изменитьдля редактирования пользователем:

<% 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>
<% } %>

Ответы [ 2 ]

1 голос
/ 22 июля 2011

Решением было изменить метод репозитория обновлений пользователей и отметить состояние объекта, измененное для адреса. Мне также нужно было добавить скрытое свойство для Address.ID в представлении редактирования пользователя.

Способ добавления / обновления хранилища пользователя

    public void InsertOrUpdate(User user)
    {
        if (user.ID == default(int)) {
            // New entity
            context.Users.Add(user);
        } else {
            // Existing entity
            context.Entry(user.Address).State = EntityState.Modified; // Update Address
            context.Entry(user).State = EntityState.Modified;
        }
    }

Дополнительное скрытое свойство при просмотре пользователем Edit

<%: Html.HiddenFor(model => model.ID) %>
<%: Html.HiddenFor(model => model.Address.ID) %> <!-- Added this line! -->

Действие редактирования контроллера

    // POST: /User/Edit/5

    [HttpPost]
    public ActionResult Edit(User user)
    {
        if (ModelState.IsValid) {
            userRepository.InsertOrUpdate(user);
            userRepository.Save();
            return RedirectToAction("Index");
        } else {
            ViewBag.PossibleAddresses = addressRepository.All;
            return View();
        }
    }
0 голосов
/ 21 июля 2011

Хитрость здесь может быть в том, чтобы использовать редактор шаблонов

По сути, создайте частичное представление в Views / Shared / EditorTemplates (создайте папку, если она не существует) с именем Address и строго типизируйте его классу адресов. Этот шаблон будет содержать ваш редактор для адреса (вырезанный из вышеупомянутого, и измените модель => модель. Адрес для модели => модель. Затем уберите все редакторы адресов из поля зрения и поместите в EditorFor (model.Address). вместо этого. Я думаю, что это будет генерировать немного другие имена полей, которые будут работать.

...