1

I'm building my site based on the patterns used in the ASP.NET Music Store project but I'm having some trouble with editing user records.

My view uses a PasswordFor for the password field and there are some fields that I need my site to update without any possible user intervention (for auditing).

My problem is that because I'm not supplying a value for password or for the auditing fields, they're submitting with null values.

Here's my POST:

[HttpPost]
public ActionResult Edit(User user)
{
    if (ModelState.IsValid)
    {
        try
        {
            // supply the Company and Role information by the PK values submitted on the view
            user.Company = db.Companies.Single(x => x.CompanyId == user.CompanyId);
            user.Role = db.Roles.Single(x => x.RoleId == user.RoleId);

            // add the auditing information
            user.ModifiedBy = String.Format("{0} {1}", Convert.ToString(Session["firstname"]), Convert.ToString(Session["lastname"]));
            user.ModifiedOn = DateTime.Now;

            // save the record
            db.Entry(user).State = EntityState.Modified;
            db.SaveChanges();

            return Json(new
            {
                Message = "Success",
                IsOK = bool.TrueString
            });
        }
        catch (Exception ex)
        {
            if (Request.IsAjaxRequest())
            {
                ThrowError(ex, "EDIT"); 
            }
            else
            {
                return RedirectToAction("Index");
            }
        }
    }
    return View(user);
}

So when I submit, because I don't want to change the password, I'm leaving it blank which means the model is getting a null value.

How can I ensure that the fields that I'm not changing aren't going to get updated?

Ortund
  • 8,095
  • 18
  • 71
  • 139
  • In the POST method, get the original from the data base, then map the properties your need from the posted model to the original, and save the original –  Feb 04 '15 at 12:22
  • I was hoping there'd be a way that was less PT... Off I go to it then – Ortund Feb 04 '15 at 12:25
  • You can also mark properties as not modified as per [this answer](http://stackoverflow.com/questions/10257360/how-to-update-not-every-fields-of-an-object-using-entity-framework-and-entitysta) –  Feb 04 '15 at 12:28
  • This has got to be a duplicate. Give me a minute to find it. In the meantime, you're looking to use a dedicated viewmodel + mapper, or the MVC BindAttribute to exclude properties you don't want to bind. – Iain Galloway Feb 04 '15 at 12:29
  • 1
    The highest-rated answer here is the simplest solution:- http://stackoverflow.com/questions/8332594/how-do-you-exclude-properties-from-binding-when-calling-updatemodel – Iain Galloway Feb 04 '15 at 12:31
  • But really the better solution is to use ViewModels:- http://stackoverflow.com/questions/11064316/what-is-viewmodel-in-mvc – Iain Galloway Feb 04 '15 at 12:32
  • 1
    I second using view models. Your database-backed entity is simply incompetent to be used as an actual model. I wish Microsoft would actually spell this out in *any* of their MVC tutorials. – Chris Pratt Feb 04 '15 at 14:05

1 Answers1

0

At first you should provide some hidden field in your form which stores ID of an entity.

Then in your controller POST action you should somehow merge your original entity with the changes done in the view. So you should do the following steps:

  • Read a record from the database.
  • Update only fields which were updated in the view model.
  • Save changes.

For the second step you can use mapping tools, for instance - https://automapper.codeplex.com/

More or less it should look like that:

var updated = SomeClass.GetByKey(key);
Mapper.CreateMap<ViewModel, Model>()
      .ForMember(dest => dest.someField, opt => opt.Ignore())
      .ForMember(dest => dest.someField2, opt => opt.Ignore());
Mapper.Map(model, updated);
//Here save changes 

(By saying view model I mean or view model or instance of your model which is bound with your view).

Arkadiusz Kałkus
  • 17,101
  • 19
  • 69
  • 108