Answered by:
How keep the original model data when execute an Edit on MVC?

Question
-
User-1651604128 posted
I am trying to implement an Audit trail in my mvc web app, the Add and Delete is easy to implement, but I have a problem in Editing an existing record.
Basically, for each editing, I need to compare each field between current UI field value and the existing value in database, and create a change log in Log table.
so I am trying to do something like this:
[HttpPost] public ActionResult Edit(ProdViewModel viewModel, string button) { ProdViewModel OrigAIGModel = viewModel; //I want to keep the original model data for comparing later, tbl_Production NewProdModel = null; ....... try { if (ModelState.IsValid) { int prodID= viewModel.SaveChanges(); //Update the record if (prodID > 0) { //after successful update above, I need to compare the data below and create a audit trail. // UpdateAuditTrail(ProdViewModel,NewProdModel.GetByID(prodID)); //here I expect to pass the old model data and new model data, //But the ProdViewModel is not the old model data, it is the updated model data, the ProdViewModel and NewProdModel is equivelent, return RedirectToAction("Edit", new { id = ProdID }); } } return View(viewModel);
Is there any way to keep the original model data before the "viewModel.SaveChanges(); ", so I can compare the two models (old model and new model ) data for auditing purpose?
Or if there is any other better solutions?
Any help is highly appreciated!
Monday, April 15, 2019 6:35 PM
Answers
-
User2053451246 posted
Retrieve the entity from the database first thing in your POST method.
var fetched = db.Table.Find(id);
if(fetched.Field != posted.Field)
{
...do something to log
fetched.Field = posted.Field
}
Then just remember to update the fetched entry to the database (instead of the posted one).
db.entry(fetched).State = EntityState.Modified;
db.SaveChanges();
- Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
Monday, April 15, 2019 7:28 PM -
User-1651604128 posted
Retrieve the entity from the database first thing in your POST method.
var fetched = db.Table.Find(id);
if(fetched.Field != posted.Field)
{
...do something to log
fetched.Field = posted.Field
}
Then just remember to update the fetched entry to the database (instead of the posted one).
db.entry(fetched).State = EntityState.Modified;
db.SaveChanges();
Thank you so much, this is an easy and simple solution, works very well.
- Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
Tuesday, April 16, 2019 6:40 PM
All replies
-
User475983607 posted
This should be handled in the database using an UPDATE trigger.
Google has a lot of information on the subject
https://stackoverflow.com/questions/12137102/sql-update-trigger-only-when-column-is-modified
SQL UPDATE Trigger reference
Monday, April 15, 2019 7:09 PM -
User2053451246 posted
Retrieve the entity from the database first thing in your POST method.
var fetched = db.Table.Find(id);
if(fetched.Field != posted.Field)
{
...do something to log
fetched.Field = posted.Field
}
Then just remember to update the fetched entry to the database (instead of the posted one).
db.entry(fetched).State = EntityState.Modified;
db.SaveChanges();
- Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
Monday, April 15, 2019 7:28 PM -
User-474980206 posted
you should also and an update timestamp, to test if the save was done after the page read, and page post back.
Monday, April 15, 2019 7:33 PM -
User-1651604128 posted
This should be handled in the database using an UPDATE trigger.
Google has a lot of information on the subject
https://stackoverflow.com/questions/12137102/sql-update-trigger-only-when-column-is-modified
SQL UPDATE Trigger reference
It seems the Update trigger is doing some coding in SQL side, no quite understand how to apply it in my situation,
I am wondering if there is any way to do it in controller side based on the C# codes I posted.
Thanks a lot,
Monday, April 15, 2019 7:35 PM -
User-474980206 posted
for an update, your code should lookup the old entity by the encrypted key passed by the post back view model. then apply the post back view model values that are allowed to be modified by the user to the entity. You can then use change tracking for audit. then save changes.
hint: you can use attributes and reflection to apply changes from the view model to the entity model, or use a tool like automapper.
Monday, April 15, 2019 9:43 PM -
User-1651604128 posted
for an update, your code should lookup the old entity by the encrypted key passed by the post back view model. then apply the post back view model values that are allowed to be modified by the user to the entity. You can then use change tracking for audit. then save changes.
hint: you can use attributes and reflection to apply changes from the view model to the entity model, or use a tool like automapper.
Sounds this is a better way, I appreciate if you can provide an example based on my example codes provided, much appreciated,
Monday, April 15, 2019 10:25 PM -
User-1651604128 posted
Retrieve the entity from the database first thing in your POST method.
var fetched = db.Table.Find(id);
if(fetched.Field != posted.Field)
{
...do something to log
fetched.Field = posted.Field
}
Then just remember to update the fetched entry to the database (instead of the posted one).
db.entry(fetched).State = EntityState.Modified;
db.SaveChanges();
Thank you so much, this is an easy and simple solution, works very well.
- Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
Tuesday, April 16, 2019 6:40 PM