How keep original value for some field when execute Edit on MVC?
Solution 1
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.
Solution 2
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();
}
Solution 3
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");
Solution 4
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)
Solution 5
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();
qakmak
Updated on November 28, 2020Comments
-
qakmak over 3 years
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.
-
Rhumborl over 9 yearsdo you even need to set
EntityState.Modified
? The EF proxy should handle this -
Kris Vandermotten over 9 yearsThis requires the action method to read and then write the row, which is two roundtrips to the database, where technically only one roundtrip is required. The select will read all "modifiable" fields to ensure the update sends only the ones actually modified. In fact, if your entity contains all columns in the table, you read them all, not just the "modifiable" ones. On the other hand, with one roundtrip you indeed don't know which fields were modified, so the update statement will send all "modifiable" columns to the database. Question is: which is worse?
-
qakmak over 9 yearsWhy use
x.FirstOrDefault()
notx.Find()
? -
StuartLC over 9 years@qakmak Yes, you can use
Find
, if you are confident that there is no chance you have a stale context. Kris - yes, I was assuming a need for an optimistic concurrency check, and also to ensure that a browser user didn't hack the JSON / POST and supply updated values for Id, Password etc. I guess an optimal solution would beUPDATE Person SET Name = {NewName}, Sex = {NewSec} WHERE ID = {OldId} AND LastUpdateTimeStamp={LastUpdateTimeStamp}
and then throw anOptimisticConcurrencyException
if the rows updated was zero, but thisn't very ORMish. -
yazanpro about 6 yearsWell you overlooked the crucial part. How do you get
id
in the post method? -
Ric .Net about 6 years@yazanpro Yes, that was a bug. Edited the answer. Funny nobody else saw this in 3 years. You probably want to put the Id field in the UserViewModel in a hidden input in your razor view
-
yazanpro about 6 yearsThanks for addressing this. However, this way we're back to the original issue which is the need to "hide" certain properties from getting tampered with by the client. If you rely on the model like you did here, the user can modify the hidden field (the user id) in JavaScript and can cause an update to a different user. The way I worked around this is by using TempData to store the ID. The good thing about
TempData
is that is lasts between requests. I'm not sure if that's the best way though. -
Ric .Net about 6 years@yazanpro The OP says nothing about tampering. The question is about not modifying data that should not be modified. This answer solves this, because only the properties that can be modified are modified. Changing the question to a security issue requires a total different answer. I have an answer for that also, not involving TempData. If you need info about this, create a new question and tag me
-
yazanpro about 6 yearsYou're right. The OP doesn't mention security. I apparently missed the point behind the question.
-
Don Gossett almost 6 yearsThis solution worked for me and seemed like the simplest approach.
-
Jamie over 5 yearsThis worked for me too, but how do I show the date on my page? I don't want it hidden because the user will want to know when the request was originally submitted - in my scenario. Thank you