模型没有在POST上填充

Nic*_*cer 0 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>
}
Run Code Online (Sandbox Code Playgroud)

所以请求看起来像这样:

__RequestVerificationToken=wcxt2SbPmLuI-FzGh7b0okDgfFIXacVKnvvuYpVkgJjpNEAgCbMzHTeMQv61xhbxch0kId6nh6mK-qoKML3CHpLOfk1SawIQIpdtVicWkys1&ID=1&Email=foo.bar%40test.com&FirstName=foo&LastName=bar
Run Code Online (Sandbox Code Playgroud)

在这里,我只想保存已编辑的值,而未包含的任何值都使用原始值.

[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);
}
Run Code Online (Sandbox Code Playgroud)

这只是一个例子来帮助我理解当对象不在表单中时如何填充,如果任何人可以详细说明或指向资源,这些资源清楚地显示当POST请求中没有明确显示值时如何填充模型太棒了

Shy*_*yju 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);
}
Run Code Online (Sandbox Code Playgroud)

在你看来

@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" />
} 
Run Code Online (Sandbox Code Playgroud)

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);
}
Run Code Online (Sandbox Code Playgroud)

在你看来

@model EditUserVM
@using(Html.Beginform())
{
  @Html.TextBoxfor(s=>s.Name)
  @Html.TextBoxfor(s=>s.Email)
  @Html.HiddenFor(s=>s.UserId)
  <input type="submit" />
} 
Run Code Online (Sandbox Code Playgroud)

在你的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");
}
Run Code Online (Sandbox Code Playgroud)

  • 是的,当然.切勿将发布的对象直接保存到数据库中.使用视图模型而不是绑定,然后将值映射到视图模型或从视图模型映射到实体. (4认同)