在MVC上执行Edit时如何保留某些字段的原始值?

qak*_*mak 13 .net c# asp.net-mvc entity-framework

如您所知,当我们想要修改数据时,我们将转到编辑页面:

public ActionResult EditAdmin(int UserId)
{ 
        User user = persons.Users.Find(id);
        return View(user);
}
Run Code Online (Sandbox Code Playgroud)

然后我们在编辑页面上提交它,它将修改:

public ActionResult EditAdmin(User user)
{ 
        persons.Entry(user).State = EntityState.Modified;
        persons.SaveChanges();
}
Run Code Online (Sandbox Code Playgroud)

但问题是,我有很多字段不需要修改:

public class User{
    public int UserId {get; set;} // do not need modify
    public int Password {get; set;} // do not need modify
    public string Name {get; set;}
    public bool Sex {get; set;}
    public DateTime AddTime {get; set;} // do not need modify
}
Run Code Online (Sandbox Code Playgroud)

显然,我无法在我的编辑页面上显示某些字段使用隐藏,因为我不希望它在UI上显示.但是当提交时,我仍然需要它仍然保留原始值.那么它有什么好主意吗?谢谢

UPDATE1:

为什么我不能用

entry.Property(e => e.Password).IsModified = false;
Run Code Online (Sandbox Code Playgroud)

链接:https://stackoverflow.com/a/18004476/1900498

但它会显示:

一个或多个实体的验证失败.有关详细信息,请参阅"EntityValidationErrors"属性.

Stu*_*tLC 21

从数据库中获取现有版本,然后只更改"可修改"字段:

public ActionResult EditAdmin(User user)
{ 
    var currentPerson = db.Persons.FirstOrDefault(p => p.id = user.id);
    if (currentPerson == null)
        return HttpNotFound();

    currentPerson.Name = user.Name;
    currentPerson.Sex = user.Sex;
    // Id and Password are not updated.

    db.SaveChanges();
}
Run Code Online (Sandbox Code Playgroud)
  • 您可能还希望进行一些乐观的并发检查,以确保更新的版本实际上是最新的.理想情况下,如果您有时间戳,请使用此选项,否则,您将面临比较所有字段.

编辑
另请参阅@Kris的评论和Ric关于创建定制视图模型的观点,因此不会使用ORM /数据层实体污染您的视图.我还认为你需要通过ViewModel携带时间戳或哈希来防止last one wins覆盖问题.

  • 你甚至需要设置`EntityState.Modified`?EF代理应该处理这个问题 (2认同)

小智 10

选项1:

您可以使用readonly属性:

就像是:

@Html.EditorFor(model => model.DriverID, new { htmlAttributes = new { 
        @Value = @Html.Action("getNextDriverID"), @readonly = "readonly"} })
Run Code Online (Sandbox Code Playgroud)

不要担心该@Value部分,因为这允许我调用一个动作方法来自动生成一个值.

在上下文中,您的看起来像:

@Html.EditorFor(model => model.UserId, new { htmlAttributes = new {@readonly = "readonly"} })
Run Code Online (Sandbox Code Playgroud)

请注意

这个答案指的是使用剃刀视图引擎.


选项2:

另一个选择是viewModel完全使用不同的:

public class edit User{

    public int userId {get; set;}
    public string Name {get; set;}
    public bool Sex {get; set;}
}
Run Code Online (Sandbox Code Playgroud)

然后在`Edit ActionResult中使用它'填充'你的数据.

然后,您可以使用(linq或其他)在[HttpPost] Action方法中设置值,然后保存到数据库中.


选项3:使用ViewBags

因为您只想编辑模型的两个部分,所以您可能只想使用ViewBag:

控制器:

ViewBag.Item1 = xyz;
ViewBag.Item2 = xyz;
Run Code Online (Sandbox Code Playgroud)

视图:

@Html.TextBox("Item1")
@Html.TextBox("Item2")
Run Code Online (Sandbox Code Playgroud)

然后在post方法中,您可以将它们添加为字符串参数:

public ActionResult Edit(string Item1, string Item2)
{
 ...
Run Code Online (Sandbox Code Playgroud)


Ric*_*Net 6

您可以并且实际上应该为您的编辑页面创建特定的视图模型.喜欢:

public class UserViewModel
{
    public string Name {get; set;}
    public bool Sex {get; set;}
}
Run Code Online (Sandbox Code Playgroud)

然后,不使用完整的用户返回视图,而是使用UserViewModel.

public ActionResult EditAdmin(int userId)
{ 
        User user = persons.Users.Find(userId);
        return View(new UserViewModel 
            { 
                Id = user.Id,
                Name = user.Name, 
                Sex = user.Sex 
            });
}

[HttpPost]
public ActionResult EditAdmin(UserViewModel user)
{ 
        var dbUser = persons.Users.Find(user.Id);
        dbUser.Name = user.Name;
        dbUser.Sex = user.Sex;

        persons.Entry(dbUser).State = EntityState.Modified;
        persons.SaveChanges();
}
Run Code Online (Sandbox Code Playgroud)