Модель Razor MVC теряет данные о действии Save

У меня есть 1 текстовое поле с использованием TextBoxFor, которое содержит данные.

У меня есть Id для модели и некоторые другие базовые данные, но отображаются как метки непосредственно в представлении.

При отправке формы только поле текстового поля содержит данные о модели, все остальное равно null, включая идентификатор. Это означает, что он не будет сохранен в базе данных.

Что приведет к тому, что все поля будут пустыми, кроме текстового поля?

Ответ 1

Так работает веб-сайт, только элементы формы представлены с формой, а метки не являются элементами формы.

Что обычно происходит, так это то, что вы:

  • Отобразить скрытое поле (Html.Hidden/Html.HiddenFor), содержащее Id вместе с текстовыми полями
  • Принять изменения в действии вашего контроллера (в качестве параметров или объекта)
  • Гидратировать экземпляр объекта, представленного Id из вашего репозитория/базы данных
  • Применить изменения к гидратированному экземпляру
  • Подтвердите состояние объекта и обновите репозиторий/базу данных (или все, что вы планируете делать с ней)

Поскольку опубликованный класс данных часто является "недопустимым" из-за его отсутствующих свойств (например, отмеченных как [Required]), его очень распространено, чтобы создать новый класс, который имеет только измененные свойства (так называемая "командная модель" "). Этот класс может иметь свои собственные свойства проверки и, таким образом, не гадать с вашей проверкой формы.

Ответ 2

Только входы отправляются обратно на сервер. Если вы хотите, чтобы модель была заполнена на основе данных на странице, они должны быть в входах (или части URL). Данные в элементах ярлыков не будут отправляться на сервер с формой (это стандартное поведение HTML-формы). Как правило, вы должны использовать скрытые поля, чтобы отправлять обратно не редактируемые данные модели или просто ссылаться на идентификатор модели и повторно заполнять базу данных, обновляя доступные для редактирования свойства (как показано ниже).

Пример:

 @(using Html.BeginForm( new { id = Model.ID } ))
 {
       <p>
           <label>Fixed Property:</label>
           @Model.SomeFixedProperty
       </p>
       <p>
          @Html.LabelFor( m => m.EditableProperty )
          @Html.TextBoxFor( m => m.EditableProperty )
       </p>
}

контроллер

[HttpPost]
public ActionResult Foo( int id, string editableProperty )
{
    var model = repo.GetById( id );
    model.EditableProperty = editableProperty;
    repo.Save();
    return View( model );
}

Ответ 3

Хотя я согласен с @RichardSzalay, другим способом было бы отметить неизмененные свойства как не измененные.

Допустим, у вас есть модель с этими свойствами: Id, Name, Email. И вы не хотите изменять электронную почту.

public ActionResult ChangeName([Bind(Include="Id,Name")] User model)
{
    // ...
    db.Entry(model).State = EntityState.Modified;
    db.Entry(model).Property(m => m.Email).IsModified = false;
    db.SaveChanges();
    // ...
}

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