Unintended Updates in ASP.NET MVC

Unintended Updates in ASP.NET MVC

In this session we will discuss how unintended updates can happen in MVC. Please read Editing Model Article of this article series before proceeding to this article. In Editing Model Article we discuss how to update the model in MVC.

We are going to work with the same example that we start in our previous article.

Let’s understand this with an example. 

At the moment, “Employee Edit” view can be used to change all of the following fields.

1. Name

2. Gender

3. City 

4. Salary

4. DateOfBirth

Let’s make “Name” non-editable. To achieve this

CHANGE THE FOLLOWING CODE IN EDIT.CSHTML
@Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "form-control" } })
TO
@Html.DisplayFor(model => model.Name)
@Html.HiddenFor(model => model.Name)

Run the application and edit an employee. Notice that Name of the employee is no longer rendered using a textbox. At this point, we may think that it is impossible for the user to change the name of the employee using the “Edit” view. That is not true. Because of the way we have written our code tools like Fiddler can be used very easily to change any properties of the “Employee” object.

Fiddler can be downloaded from the following URL

https://www.telerik.com/download/fiddler

After we have downloaded and installed fiddler, run fiddler, and navigate to the following URL

http://localhost:54094/Employee/Edit/1

Select the Composer Tab

Select method as GET

Provide the URL as http://localhost:54094/Employee/Edit/1

Click on execute button as shown below

Unintended Updates in ASP.NET MVC

In fiddler in web sessions window, select the URL. Under the “Inspectors” tab we can see Request headers and response. We will discuss more fiddler in a later session.

To see this click on the below URL

Unintended Updates in ASP.NET MVC

Then select the web view as shown below

Unintended Updates in ASP.NET MVC

Now click on “Save” button on “Edit” view. Notice that under “Web Sessions” in fiddler another request is captured for the same URL –

http://localhost:54094/Employee/Edit/1

Now without using the browser, let’ us see how to generate a post request using fiddler.

1. Click on “Composer” tab in fiddler

2. Drag and drop the following URL from “Web Sessions” window onto Composer window.

http://localhost:54094/Employee/Edit/1

3. In “Request Body” under “Composer” tab change “Name” of the employee to “XYZ”

4. Finally, click the “Execute” button on “Fiddler”

Now either query the database table or navigate to “Index” view and notice that the employee name is changed to “XYZ”.

Let’s see how to prevent unintended update

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.GetAllEmployess().Single(x => x.ID == id);
    UpdateModel(employee, new string[] { "ID", "Gender", "City", "Salary", "DateOfBirth" });
    if (ModelState.IsValid)
    {
        employeeBusinessLayer.UpdateEmmployee(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, Salary & DateOfBirth) from the database. 

Employee employee = employeeBusinessLayer.GetAllEmployess().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 including a list or white list. Notice that we did not include “Name” property in the list. This means even if the posted form data contains the 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”, “Salary”,”DateOfBirth” });

So, if we were generate a post request using fiddler “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.GetAllEmployess().Single(x => x.ID == id);
    UpdateModel(employee, null, null, new string[] { "Name" });
    if (ModelState.IsValid)
    {
        employeeBusinessLayer.UpdateEmmployee(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) 

In the next article, I will discuss how to use Bind parameter to include and exclude properties from model binding in ASP.NET MVC application

SUMMARY

In this article, I try to explain how unintended updates can happen in ASP.NET MVC application and how to prevent unintended update in ASP.NET MVC application step by step with a simple example. I hope this article will help you with your need. I would like to have your feedback. Please post your feedback, question, or comments about this article.

Leave a Reply

Your email address will not be published. Required fields are marked *