Reputation: 1290
I have a more or less standard looking model:
public class Project {
public int ID { get; set; }
//... some more properties
public DateTime StartDate { get; set; }
public int Duration { get; set; }
}
If the user modifies StartDate
or project Duration
, I have to call a function to update a simulation. In order to achieve this I'd like to detect the state change of the fields StartDate
and Duration
within a controller.
Something like that:
if(project.StartDate.stateChange() || project.Duration.stateChange())
Here is an example of what the Controller Method would look like:
[HttpPost]
public ActionResult Edit(Project project)
{
if (ModelState.IsValid)
{
if(project.StartDate.stateChange() || project.Duration.stateChange())
doSomething();
db.Entry(project).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(project);
}
Any idea, how can I achieve this?
Upvotes: 7
Views: 22449
Reputation: 1256
I believe you can compare the edited entity with the original one read from the database.
Something like:
public ActionResult Edit(Project project)
{
if (ModelState.IsValid)
{
var original = db.Find(project.ID);
bool changed = original.StartDate != project.StartDate || original.Duration != project.Duration;
if (changed)
{
original.StartDate = project.StartDate;
original.Duration = project.Duration;
doSomething();
db.Entry(original).CurrentValues.SetValues(project);
db.SaveChanges();
}
}
return View(project);
}
Upvotes: 10
Reputation: 285
Use .AsNoTracking().FirstOrDefault to retrieve the original object for comparison:
public ActionResult Edit(Project project)
{
if (ModelState.IsValid)
{
Project original = db.AsNoTracking().FirstOrDefault( p => p.ID == project.ID);
if (original.StartDate != project.StartDate || original.Duration != project.Duration)
doSomething();
db.Entry(project).State = EntityState.Modified;
db.SaveChanges();
}
return View(project);
}
Upvotes: 2
Reputation: 81
You can solve it by carrying old values via ViewBag.
In action:
public ActionResult Edit(int? id)
{
//...Your Code
ViewBag.OrigStartDate = project.StartDate;
ViewBag.OrigDuration = project.Duration;
return View(project);
}
Add hidden elements to View
...
@Html.Hidden("OrigStartDate", (DateTime)ViewBag.OrigStartDate)
@Html.Hidden("OrigDuration", (int)ViewBag.OrigDuration)
...
Add these parameters to the post method and check them for changes
[HttpPost]
public ActionResult Edit(DateTime OrigStartDate, int OrigDuration)
{
if (ModelState.IsValid)
{
if (OrigStartDate != project.StartDate || OrigDuration != project.Duration)
doSomething();
db.Entry(project).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.FileTypeId = new SelectList(db.FileTypes, "Id", "TypeName", dbinfo.FileTypeId);
return View(project);
}
Upvotes: 8
Reputation: 4504
If you want to do it without querying your persistance layer I guess adding the old values as fields in your model and then keep them in the page as hidden fields is the easiest way to solve this.
So add CurrentStartDate and CurrentDuration in your model:
public class Project {
public int ID { get; set; }
//... some more properties
public DateTime StartDate { get; set; }
public int Duration { get; set; }
public DateTime CurrentStartDate { get; set; }
public int CurrentDuration { get; set; }
}
and then add the hidden fields with the old values in your view:
@Html.HiddenFor(model => model.CurrentStartDate )
@Html.HiddenFor(model => model.CurrentDuration )
This will give you something to compare the selected values with in your controller action.
Upvotes: 2