Support us .Net Basics C# SQL ASP.NET Aarvi MVC Slides C# Programs Subscribe Download

Part 20 - Preventing unintended updates in mvc

Suggested Videos 
Part 17 - Editing a model
Part 18 - Updating data
Part 19 - Unintended updates



In this video we will discuss, preventing unintended updates in mvc. Please watch Part 19, before proceeding. 



Modify "Edit" controller action method that is decorated with [HttpPost] attribute as shown below. This method is present in "EmployeeController.cs" file.
[HttpPost]
[ActionName("Edit")]
public ActionResult Edit_Post(int id)
{
    EmployeeBusinessLayer employeeBusinessLayer = new EmployeeBusinessLayer();

    Employee employee = employeeBusinessLayer.Employees.Single(x => x.ID == id);
    UpdateModel(employee, new string[] { "ID", "Gender", "City", "DateOfBirth" });
            
    if (ModelState.IsValid)
    {
        employeeBusinessLayer.SaveEmployee(employee);

        return RedirectToAction("Index");
    }

    return View(employee);
}

Please note:
1. The name of the method is changed from "Edit" to "Edit_Post"
2. The method is decorated with [ActionName("Edit")] and [HttpPost] attributes. This indicates that, this method is going to respond to "Edit" action, when the form is posted to the server.
3. The "id" of the employee that is being edited, is passed as a parameter to this method.
4. Using the "id" parameter we load the employee details(Id, Name, Gender, City & DateOfBirth) from the database. 
Employee employee = employeeBusinessLayer.Employees.Single(x => x.ID == id);
5. We then call UpdateModel() function. This should automatically update "Employee" object with data from the posted form. We are also passing a string array as the second parameter. This parameter specifies the list of model properties to update. This is also called as include list or white list. Notice that, we did not include "Name" property in the list. This means, even if the posted form data contains value for "Name" property, it will not be used to update the "Name" property of the "Employee" object.
UpdateModel(employee, new string[] { "ID", "Gender", "City", "DateOfBirth" });

So, if we were to generate a post request using fiddler as we did in the previous session, "Name" property of the "Employee" object will not be updated.

Alternatively, to exclude properties from binding, we can specify the exclude list as shown below. 
[HttpPost]
[ActionName("Edit")]
public ActionResult Edit_Post(int id)
{
    EmployeeBusinessLayer employeeBusinessLayer = new EmployeeBusinessLayer();

    Employee employee = employeeBusinessLayer.Employees.Single(x => x.ID == id);
    UpdateModel(employee, null, null, new string[] { "Name" });

    if (ModelState.IsValid)
    {
        employeeBusinessLayer.SaveEmployee(employee);

        return RedirectToAction("Index");
    }

    return View(employee);
}

Notice that we are using a different overloaded version of UpdateModel() function. We are passing "NULL" for "prefix" and "includeProperties" parameters.
UpdateModel<TModel>(TModel model, string prefix, string[] includeProperties, string[] excludeProperties)

6 comments:

  1. Just wondering, wouldn't it be better to modify 'spSaveEmployee' store-procedure to exclude name from being updated?

    ReplyDelete
    Replies
    1. In my opinion, this would depend on your business logic.

      Say you have a call center and the Customer Service Reps can update some records but the Call Center Manager does not want any Customer Service reps to change names, only the supervisors and above can.

      If you were to comment out the @name in the stored procedure then you would have to create a second stored procedure that an admin/manager page would use to allow supervisors and above to use to change the name. This would be serious code duplication and is not recommended.

      However, I have never worked for a company that did not allow anyone to change names in the database. I believe the video was just using an example and the 'name' happened to be the field selected to not allow to be updated. Peoples name change or are misspelled and an incorrectly spelled name usually doesn't cause major problems unless the database was poorly designed and the name is the key.

      A real word example would be an Insurance claims system where the claim number is very important for proper processing and only claim managers should be able to change the claim number. Everyone else can only view the claim number.

      Just my two cents...
      John

      Delete
  2. Thanks for your greate tutorials that help me a lot! Could anyone show me how to update a model into database just using linq that can exclude the field we don't need? Thank you very much

    ReplyDelete
  3. For avoiding Name field to be updated, we can also use @readonly = "readonly" like below :
    @Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "form-control", @readonly = "readonly" } })

    ReplyDelete
  4. What if we edit ID field in fiddler and submit, unintended updates will happen in that case right, so how to prevent from editing ID field??

    ReplyDelete

It would be great if you can help share these free resources