Modifying Posted Variable Value In Controller Action

Generally this is not something I would do as the data the user captures is what they intend to persist or send. I have however seen use cases where the controller has a bool field that determines if an UPDATE or INSERT is required.

Scenario

  1. A user partially fills out a form that persists the data to more than one table, each table schema is defined by a property class on the view model
  2. The user clicks save, the data is then persisted to the database (INSERT required)
  3. The user then fills out more of the form and then clicks save again (UPDATE required)

The class could look something like this

1
2
3
4
5
6
7
8
9
public class ClientScheduleViewModel
{
[Required(ErrorMessage = "Client required.")]
public string ClientId { get; set; }

public UserInformationViewModel DisplayInfo { get; set; }
public UserCaptureModel CaptureInfo { get; set; }
public bool DoInsert{ get; set; }
}

The DisplayInfo and CaptureInfo property’s could be passed to a partial view, one to display and one to capture.

When the view model data is posted back to the controller, DoInsert being true would indicate a new record is required and false means an update where the lookup on both tables could be done by ClientId.

When ActionResult returns controls and data binds to the view, DoInsert would still display the value that was posted. This is probably a security thing.

There are 3 shims to get around this as suggested by Darin Dimitrov on stack overflow. (the below has been adapted for my example)

  1. Remove the value from the modelstate:
1
2
3
4
5
6
7
[HttpPost]
public ActionResult Foo(SomeModel model)
{
ModelState.Remove("DoInsert");
model.DoInsert = false; //change after doing the insert
return View(model);
}
  1. Manually generate the hidden field
1
<input type="hidden" name="DoInsert" value="<%= Model.DoInsert %>" />
  1. Write a custom helper which will use the value of your model and not the one that’s being POSTed

Option 2 is probably the best route as there is no hard coding.

Alternative Solutions

  1. Include the database id as a hidden field (additional validations will be needed to ensure the user did not maliciously change values)
  2. Store the id in a session or cookie (for the cookie option you should obfuscate or encode the data)

References