Модель 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();
// ...
}
Недостатком является то, что вы можете столкнуться с проблемами проверки из-за недостающих полей в модели.