ASP.NET MVC 3 - EF 4.2, сначала код - редактирование основных деталей - PullRequest
1 голос
/ 16 января 2012

Я озадачен проблемой в ASP.NET MVC 3 - обработкой редактирования и обновлением отношения мастер-деталь из одного представления MVC.

Я использую Entity Framework 4.2 сначала для создания небольшого приложения. Он использует класс Person (который имеет Name, FirstName и т. Д.) И класс AddressStreet, Zipcode, City и т. Д.).

Эти два класса имеют отношение m: n друг к другу, смоделировано в EF-коде сначала:

public class Person
{
    private List<Address> _addresses;

    // bunch of scalar properties like ID, name, firstname

    public virtual List<Address> Addresses
    {
        get { return _addresses; }
        set { _addresses = value; }
    }
}

public class Address
{
    private List<Person> _people;

    // bunch of scalar properties like AddressID, street, zip, city

    public virtual List<Person> People
    {
        get { return _people; }
        set { _people = value; }
    }
}

Я заполнил базу данных вручную некоторыми данными, и поиск данных с помощью EF 4.2 работает просто отлично.

У меня есть ASP.NET MVC PersonController, в который я загружаю Person, включая все его текущие адреса, и показываю его в режиме Razor. Я хотел бы позволить пользователю изменять или обновлять существующие адреса, а также удалять или вставлять адреса. Контроллер получает данные для этого человека из службы WCF, например:

public ActionResult Edit(int id)
{
    Person person = _service.GetPerson(id);
    return View(person);
}

и адреса человека заполняются правильно при получении.

Представление для этого работает отлично - оно показывает все данные из экземпляра Person, как ожидалось.

@model DomainModel.Person

<h2>Edit</h2>

@using (Html.BeginForm()) {
    @Html.ValidationSummary(true)
    <fieldset>
        <legend>Person</legend>

        @Html.HiddenFor(model => model.PersonId)

        <div class="editor-label">
            @Html.LabelFor(model => model.Name)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Name)
            @Html.ValidationMessageFor(model => model.Name)
        </div>

        .... and a few more of those scalar properties being edited....  

        <hr/>
        <h4>Addresses</h4>

        @foreach (var item in Model.Addresses)
        {
            <tr>
                <td>
                    @Html.EditorFor(modelItem => item.Street)
                </td>
                <td>
                    @Html.EditorFor(modelItem => item.ZipCode)
                </td>
                <td>
                    @Html.EditorFor(modelItem => item.City)
                </td>
            </tr>
        }
        <hr/>
        <p>
            <input type="submit" value="Save" />
        </p>
    </fieldset>
}

Однако, когда я пытаюсь обработать POST после сохранения редактируемого лица, я не могу получить доступ к адресам, которые были отображены (и, возможно, отредактированы) в представлении:

    [HttpPost]
    public ActionResult Edit(Person person)
    {
        if (ModelState.IsValid)
        {
            _service.UpdatePerson(person);
            return RedirectToAction("Index");
        }
        return View(person);
    } 

В этом случае свойство person.Addresses всегда равно нулю. Хм .... чего мне не хватает ?? Как я могу отредактировать отношение «Персона-к-адресам» в представлении ASP.NET MVC и получить из моего представления Person И , связанного с ним Addresses, чтобы я мог передать их в EF для сохранить их обратно в таблицы базы данных ??

Ответы [ 2 ]

2 голосов
/ 16 января 2012

Я полагаю, что вы получите желаемый эффект, изменив блок foreach на блок for следующим образом:

    @for (var i = 0; i < Model.Addresses.Count(); i++)
    {
        <tr>
            <td>
                @Html.EditorFor(model => model.Addresses[i].Street)
            </td>
            <td>
                @Html.EditorFor(model => model.Addresses[i].ZipCode)
            </td>
            <td>
                @Html.EditorFor(model => model.Addresses[i].City)
            </td>
        </tr>
    }

Это, конечно, требует, чтобы коллекция адресов была доступна по индексу.

Причина этого в том, что в блоке foreach результирующий html будет выглядеть примерно так:

<input type="text" name="Street" value="Test Street 1" />

Блок for вместо этого сгенерирует что-то вроде:

<input type="text" name="Addresses[0].Street" value="Test Street 1" />

Связыватель модели затем использует имя поля формы, чтобы сопоставить его со свойствами класса модели.

Оба примера упрощены для объяснения и не на 100% правильны.

2 голосов
/ 16 января 2012

Я подозреваю, что поля ввода для адреса имеют неправильные имена.

Я бы предложил вам использовать шаблоны редактора. Поэтому замените ваш цикл @foreach в представлении Razor одним вызовом помощника EditorFor для свойства Addresses:

<h4>Addresses</h4>

@Html.EditorFor(x => x.Addresses)

<hr/>

и теперь определите шаблон редактора для адреса, который будет автоматически отображаться для каждого элемента коллекции (~/Views/Shared/EditorTemplates/Address.cshtml):

@model Address
<tr>
    <td>
        @Html.EditorFor(x => x.Street)
    </td>
    <td>
        @Html.EditorFor(x => x.ZipCode)
    </td>
    <td>
        @Html.EditorFor(x => x.City)
    </td>
</tr>

Теперь, когда вы отправляете, свойство Addresses в вашей модели Person будет правильно связано.

Примечание: шаблон редактора также может быть размещен внутри ~/Views/XXX/EditorTemplates/Address.cshtml, где XXX - текущий контроллер. В этом случае его можно повторно использовать только в представлениях текущего контроллера вместо того, чтобы сделать его глобально видимым (поместив его в Shared).

Для более глубокого обзора того, как формат проводов связующего устройства модели по умолчанию, вы можете взглянуть на следующую статью .

...