模型没有在POST上填充

时间:2015-11-02 15:04:37

标签: c# asp.net-mvc entity-framework-6

我创建了一个简单的类来直接测试它,在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中没有明确显示值时如何填充模型要求很棒。

1 个答案:

答案 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");
}