我创建了一个简单的类来直接测试它,在Edit POST操作中,如果一个属性不在表单中,我将使用数据库中已存在的值,而不是它被设置为null并覆盖任何值。
这是来自脚手架生成,假设我注释掉密码和密码确认,因为我不希望他们编辑它,所以他们将被排除在POST值之外。
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>User</h4>
<hr />
@Html.ValidationSummary(true)
@Html.HiddenFor(model => model.ID)
<div class="form-group">
@Html.LabelFor(model => model.Email, new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Email)
@Html.ValidationMessageFor(model => model.Email)
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.FirstName, new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.FirstName)
@Html.ValidationMessageFor(model => model.FirstName)
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.LastName, new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.LastName)
@Html.ValidationMessageFor(model => model.LastName)
</div>
</div>
@*<div class="form-group">
@Html.LabelFor(model => model.Password, new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Password)
@Html.ValidationMessageFor(model => model.Password)
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.PasswordConfirmation, new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.PasswordConfirmation)
@Html.ValidationMessageFor(model => model.PasswordConfirmation)
</div>
</div>*@
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
}
所以请求看起来像这样:
__RequestVerificationToken=wcxt2SbPmLuI-FzGh7b0okDgfFIXacVKnvvuYpVkgJjpNEAgCbMzHTeMQv61xhbxch0kId6nh6mK-qoKML3CHpLOfk1SawIQIpdtVicWkys1&ID=1&Email=foo.bar%40test.com&FirstName=foo&LastName=bar
在这里,我只想保存已编辑的值,而未包含的任何值都使用原始值。
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include="ID,Email,FirstName,LastName,Password,PasswordConfirmation")] User user)
{
if (ModelState.IsValid)
{
db.Entry(user).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(user);
}
这只是一个例子,可以帮助我理解当对象不在表单中时如何填充,如果有人可以详细说明或指向资源,这些资源清楚地显示了当POST中没有明确显示值时如何填充模型要求很棒。
答案 0 :(得分:5)
如果财产不是以它的形式存在,我就会感到印象深刻 使用数据库中已存在的值
事实并非如此。表单(只是客户端浏览器中的一些HTML)如何知道数据库中的值是什么?
你有2个解决方案
1)在您的HttpGet方法中,将实体的所有属性发送到表单,但不要向用户显示这些属性。保留在表单内的隐藏字段中,当您发布表单时,它将可用。
public ActionResult Edit(int id)
{
var vm = new EditUserVM();
var user = GetUserFromYourDb(id);
vm.Name = user.Name
vm.Email= user.Email
//The below property you don't want user to edit in form. But still sending.
vm.Token= user.Token
return View(vm);
}
在您的视图中
@model EditUserVM
@using(Html.Beginform())
{
@Html.TextBoxfor(s=>s.Name)
@Html.TextBoxfor(s=>s.Email)
<!-- Hidden field here -->
@Html.HiddenFor(s=>s.Token)
@Html.HiddenFor(s=>s.UserId)
<input type="submit" />
}
2)如果您不希望将所有字段发送到表单,您可以试试这个。(我推荐这个)。只有您希望用户在GET表单中编辑的字段,在HttpPost操作方法中,再次从数据库中读取现有实体,并使用从表单中收到的值更新字段。您的其他字段值保持不变。
public ActionResult Edit(int id)
{
var vm = new EditUserVM();
var user = GetUserFromYourDb(id);
vm.Name = user.Name
vm.Email= user.Email
return View(vm);
}
在您的视图中
@model EditUserVM
@using(Html.Beginform())
{
@Html.TextBoxfor(s=>s.Name)
@Html.TextBoxfor(s=>s.Email)
@Html.HiddenFor(s=>s.UserId)
<input type="submit" />
}
在你的HttpPost中
[HttpPost]
public ActionResult Edit(EditUserVM model)
{
var existingUser = GetUserFromYourDb(model.UserId);
existingUser.Name = model.Name;
existingUser.Email = model.Email;
SaveUser(existingUser);
return RedirectToAction("UserSaved");
}