简体   繁体   中英

How keep original value for some field when execute Edit on MVC?

As you know, When we want to Modify a data, We will go to Edit page:

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

Then We submit it on the Edit Page, it will Modify:

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

But the problem is , I have alot of field don't need be modify :

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
}

Obviously, I can't display some field on my edit page use Hidden , because I don't want it display on UI. but when submit, I still need it still keep the original value . So Is there any good idea for it? Thanks

Update1:

Why I can't use like

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

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

But It will display :

Validation failed for one or more entities. See 'EntityValidationErrors' property for more details.

Fetch the existing version from the database, and then change just the 'modifiable' fields:

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();
}
  • You might also want to do some optimistic concurrency checking as well, to ensure that the version being updated, is in fact current. Ideally, if you have a timestamp, use this, otherwise, you are faced with comparing all fields.

Edit
See also @Kris' comment and Ric's point about creating tailored view models and hence NOT polluting your views with ORM / data tier entities. I also still contend you need to carry a timestamp or hash through the ViewModel to prevent the last one wins overwriting problem.

Option 1:

You could use a readonly attribute:

Something like:

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

Don't worry about the @Value part as this allows me to call an action method to auto generate a value.

In context, yours would look like:

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

Please Note

This answer refers to using razor view engine.


Option 2:

Another option would be to use a different viewModel altogether:

public class edit User{

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

And then 'fill' your data using this in your `Edit ActionResult.

from there, you could then set the values in your [HttpPost] Action method using (linq or otherwise), before then saving to your database.


Option 3: Using ViewBags

since you are only looking to edit 2 parts of your model, you might just want to use the ViewBag :

Controller:

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

View:

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

Then in your post method, you could add these as string parameters:

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

You could and actually should make a specific viewmodel for your edit page. Like:

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

Then instead of returning the complete user to and from the view, use the 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();
}

Here is something I just learned how to do for Posting the data to a database and excluding other fields. I only wanted to post 1 change to my database on PIVPrinted checkbox.

[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");

Using the Razor view engine you can mark the entry as hidden:-

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

Or just this which is simpler:-

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

If you dont want use hidden in view you must load yor entity from db and add yor changes like

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)

No need to do anything else, just list the constant values as Razor syntaxes.

For modifying just a few fields I use the following code and I think You too can make use of it.

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

    db.SaveChanges()          
 }

simple and easy solution is to use sessions. In Edit get method just create session and assign value of that particular object for example.

Session["ProfilePic"] = personnel.ProfilePic;

now in Edit Post method set the value

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

offcourse in Edit post method you will check the condition when your particular object value is null.

You can use TempData like this:

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

Then you can recover it after post:

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

It's necessary to check TempData["oldUser"] == null because in case of errors or user backing to page sometimes the TempData is lost.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM