简体   繁体   中英

Detect state change of model property, in controller, using Entity Framework

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?

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

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

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.

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

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