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

本文关键字:字段 原始 何保持 MVC 执行 Edit | 更新日期: 2023-09-27 18:27:38

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

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
}

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

更新1:

为什么我不能像一样使用

entry.Property(e => e.Password).IsModified = false;

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

但它会显示:

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

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

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

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:

您可以使用只读属性:

类似于:

@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"} })

请注意

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


选项2:

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

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

然后在"编辑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)
{
 ...

您可以而且实际上应该为您的编辑页面创建一个特定的视图模型。类似:

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();
}

以下是我刚刚学到的将数据发布到数据库并排除其他字段的方法。我只想在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");

使用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)

如果你不想在视图中使用隐藏,你必须从数据库加载yor实体,并添加像这样的yor更改

var olduser= db.Persons.FirstOrDefault(p => p.id = user.id);
olduser.Name=user.Name; 
olduser.Sex=user.Sex;
persons.SaveChanges();
 @Html.HiddenFor(model => model.UserId)
 @Html.HiddenFor(model => model.Password)
 @Html.HiddenFor(model => model.AddTime)

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

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

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

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

Session["ProfilePic"] = personnel.ProfilePic;

现在在Edit Post方法中设置值

personnel.ProfilePic = Session["ProfilePic"].ToString();

当然,在Edit post方法中,当您的特定对象值为null时,您将检查条件。

您可以像这样使用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会丢失。