Помогите с привязкой вложенной модели asp.net mvc - PullRequest
4 голосов
/ 23 июля 2011

Итак, у меня почти полностью работает этот демонстрационный проект.

public class Project
    {
        public int ID { get; set; }
        [Required]
        public string Name { get; set; }
        public virtual ICollection<Task> Tasks { get; set; }

    }

    public class Task
    {
        public int ID { get; set; }
        [Required]
        public string Name { get; set; }
        public int ProjectID { get; set; }

        public virtual Project Project { get; set; }

    }

Контроллер

public ActionResult Edit(int id)
        {           
            var project = db.Projects.Where(p=>p.ID==id).Single();
            return View(project);
        }

        [HttpPost]
        public ActionResult Edit(Project project)
        {
            if (ModelState.IsValid)
            {
                var dbProject = db.Projects.Where(p => p.ID == project.ID).Single();

                UpdateModel(dbProject);
                db.SaveChanges();                
                TempData["Success"] = "Modelo Valido";
            }
            return RedirectToAction("Index");
        }

Вид // строго типизирован для проекта

@using (Html.BeginForm())
{
    @Html.ValidationSummary(true)
    <fieldset>
        <legend>Project</legend>
        @Html.HiddenFor(model => model.ID)
        <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>
        <h1>Tasks</h1>
        @Html.EditorFor(m => m.Tasks)
        <p>
            <input type="submit" value="Save" />
        </p>
    </fieldset>
}

EditorTemplate

@model MvcApplication2.Models.Task
<span>Task</span>
<br />
    @Html.LabelFor(m => m.Name)
    @Html.EditorFor(m => m.Name)
    @Html.HiddenFor(m => m.ID)
    @Html.HiddenFor(m => m.ProjectID)
    @Html.ValidationMessageFor(m => m.Name)

В представлении отображается это

enter image description here

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

Операция не выполнена: связь не может быть изменена, так как одно или несколько свойств внешнего ключа не могут иметь значение NULL.Когда в отношение вносится изменение, для соответствующего свойства внешнего ключа устанавливается нулевое значение.Если внешний ключ не поддерживает нулевые значения, необходимо определить новое отношение, свойству внешнего ключа должно быть назначено другое ненулевое значение или несвязанный объект должен быть удален.

Здесьэто фотография моего результата точки останова отладки

enter image description here

Пожалуйста, помогите.

ОБНОВЛЕНИЕ:

Я изменил свойДействие контроллера для этого

[HttpPost]
        public ActionResult Edit(Project project)
        {
            if (ModelState.IsValid)
            {
                db.Entry(project).State = EntityState.Modified;
                db.SaveChanges();                
                TempData["Success"] = "Modelo Valido";
                return RedirectToAction("Index");
            }
            return View(project);
        }

все еще не работает правильно.Теперь изменения, внесенные в Название проекта, корректно обновляются в базе данных.но изменения, внесенные в любое имя задачи, полностью игнорируются.

Ответы [ 2 ]

4 голосов
/ 23 июля 2011

Я полагаю, что @Html.EditorFor(m => m.Tasks) генерирует html как (приблизительно)

<label>Name</label>
<input type="text" name="Tasks[0].Name" id="auto-gen-id"/>
<input type="hidden" name="Tasks[0].ID" id = "auto-gen-id"/>
<input type="hidden" name="Tasks[0].ProjectID" id = "auto-gen-id"/>
<!--html for validation span-->

Выше приведен примерный html, сгенерированный для первой задачи в коллекции, и аналогичный html будет сгенерирован для каждой задачи в коллекции.Единственное отличие состоит в том, что индекс будет увеличиваться в атрибутах имени всех входных данных, т.е. Tasks[1].Name, Tasks[1].ProjectID и т. Д. Эта часть будет фактически привязана к свойству Collection<Task> Tasks Project, но вы можете видеть, что в детальной части вы надеваетене имеет никаких входных данных, таких как

<input type="whatever" name="Tasks[0].Project.ProjectID" .../>
<input type="whatever" name="Tasks[0].Project.Name" ..../>

Для Modelbinder требуются элементы ввода с соответствующими соглашениями об именах, чтобы связать значения со всеми свойствами параметров метода действия.Для целей тестирования вы можете включить эти две строки в шаблон Редактора для Задачи

@Html.TextBoxFor(x=>x.Project.ID)
@Html.TextBoxFor(x=>x.Project.Name)

, ввести для них правильные значения в форме, и у вас будет свойство Project Задачи, заполненное этими значениями.Но это может быть не то, что вы хотите, т.е. вводить информацию о проекте дважды, и это может не понадобиться (если вы используете Linq для sql, это точно не нужно).Когда вы вызываете ORM для присоединения сущностей к сущностям БД, он узнает, к каким элементам проекта относится текущая задача.
Примечание: Если у вас есть проблемы с привязкой модели, всегда обращайте внимание на сгенерированный html.Сгенерированный html будет определять, какие значения формы будут сопоставляться с какими свойствами модели, если вы используете связыватель моделей по умолчанию.это становится особенно важным, если у вас есть сценарий с мастер-деталями, как в вашем примере.

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

Я нашел способ заставить это работать, но я не совсем доволен этим подходом.

см. Этот вопрос о том, как реорганизовать мой текущий код, чтобы увидеть, как я в настоящее время (надеюсь, временно сделаю это)

Помогите улучшить (рефакторинг) мой код.Automapper - EF - asp.net mvc-3

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