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

时间:2014-10-24 11:19:49

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

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

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

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

public ActionResult EditAdmin(User user)
{ 
        persons.Entry(user).State = EntityState.Modified;
        persons.SaveChanges();
}

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

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
}

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

UPDATE1:

为什么我不能像

一样使用
entry.Property(e => e.Password).IsModified = false;

link:https://stackoverflow.com/a/18004476/1900498

但它会显示:

  

一个或多个实体的验证失败。看到   'EntityValidationErrors'属性以获取更多详细信息。

10 个答案:

答案 0 :(得分: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();
}
  • 您可能还想进行一些乐观的并发检查,以确保正在更新的版本实际上是最新的。理想情况下,如果您有时间戳,请使用此选项,否则,您将面临比较所有字段。

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

答案 1 :(得分:10)

选项1:

您可以使用只读属性:

类似的东西:

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

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

在上下文中,您的内容如下:

@Html.EditorFor(model => model.UserId, new { htmlAttributes = new {@readonly = "readonly"} })

请注意

这个答案指的是使用 razor view 引擎。


选项2:

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

public class edit User{

    public int userId {get; set;}
    public string Name {get; set;}
    public bool Sex {get; set;}
}

然后在你的`Edit ActionResult。

中使用它来“填充”你的数据

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


选项3:使用ViewBags

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

控制器:

ViewBag.Item1 = xyz;
ViewBag.Item2 = xyz;

查看:

@Html.TextBox("Item1")
@Html.TextBox("Item2")

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

public ActionResult Edit(string Item1, string Item2)
{
 ...

答案 2 :(得分:6)

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

public class UserViewModel
{
    public string Name {get; set;}
    public bool Sex {get; set;}
}

然后,不是将完整的用户返回到视图,而是使用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();
}

答案 3 :(得分:4)

我刚刚学会了如何将数据发布到数据库并排除其他字段。我只想在PIVPrinted复选框上将1个更改发布到我的数据库。

[HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult PrintDetails([Bind(Include = "PatientID,LastName,FirstName,PatientDOB,PIVCompleted,PIVPrinted")] PIV pIV,
        string command)
    {

        if (command.Equals("Print Completed"))

        {
            pIV.PIVPrinted = false;
            db.Entry(pIV).State = EntityState.Unchanged;
            db.Entry(pIV).Property("PIVPrinted").IsModified = true;
            db.SaveChanges();

            return RedirectToAction("PrintDetails");

答案 4 :(得分:2)

使用Razor视图引擎,您可以将条目标记为隐藏: -

    <div class="form-group" style="visibility:hidden;height:0px;">
            @Html.EditorFor(model => model.CreationDate)
            @Html.ValidationMessageFor(model => model.CreationDate, "", new { @class = "text-danger" })
    </div>

或者只是这个更简单: -

    @Html.HiddenFor(model => model.CreationDate)

答案 5 :(得分:1)

如果您不想在视图中使用隐藏,则必须从db加载yor实体并添加yor更改,如

var olduser= db.Persons.FirstOrDefault(p => p.id = user.id);
olduser.Name=user.Name; 
olduser.Sex=user.Sex;
persons.SaveChanges();

答案 6 :(得分:1)

gcc 4.4.7

无需执行任何其他操作,只需将常量值列为Razor语法。

答案 7 :(得分:0)

为了修改几个字段,我使用下面的代码,我想你也可以使用它。

if (ModelState.IsValid)
{
    var action = this.db.DbcontextName.Find(int.Parse(id));   
    db.Entry(action).Property("Status").CurrentValue = "YourString/Data";

    db.SaveChanges()          
 }

答案 8 :(得分:0)

简单易用的解决方案是使用会话。在Edit get方法中,只需创建会话并分配该特定对象的值。例如。

Session["ProfilePic"] = personnel.ProfilePic;

现在在Edit Post方法中设置值

personnel.ProfilePic = Session["ProfilePic"].ToString();
编辑post方法中的

offcourse,您将在特定对象值为空时检查条件。

答案 9 :(得分:0)

您可以这样使用 TempData

public ActionResult EditAdmin(int UserId) { User user = persons.Users.Find(id); TempData["oldUser"] = user; return View(user); }

然后您可以在发布后将其恢复:

public ActionResult EditAdmin(User user) { User oldUser = TempData["oldUser"] == null ? persons.Users.Find(user.UserId) : (User) TempData["oldUser"]; if (oldUser.Sex != user.Sex) doSomething(); persons.Entry(user).State = EntityState.Modified; persons.SaveChanges(); }

必须检查TempData [“ oldUser”] == null,因为在发生错误或用户返回页面时,有时TempData会丢失。