Use View Models instead of FormCollection
January 20, 2010
I have recently been spending quite a bit of time on StackOverflow and I noticed that quite a few of the MVC-related answers make use of the FormCollection class. If you’re unfamiliar with this class, here is an example of how it gets used:
<% using (Html.BeginForm("Add", "Contacts", FormMethod.Post)) { %>
<label for="Name">Name:</label><input type="text" name="Name" /><br />
<label for="Surname">Surname:</label><input type="text" name="Surname" /><br />
<label for="CellNumber">Cellphone Number:</label><input type="text" name="CellNumber" /><br />
<input type="submit" value="Add" />
<% } %>
public ActionResult Add(FormCollection formValues)
{
var contact = new Contact();
contact.Name = formValues["Name"];
contact.Surname = formValues["Surname"];
contact.CellNumber = formValues["CellNumber"];
service.Add(contact);
return RedirectToAction("Index");
}
Which of course works exactly as expected. Let’s take a look at the same example using a view model.
public class ContactViewModel
{
public string Name { get; set; }
public string Surname { get; set; }
public string CellNumber { get; set; }
}
public ActionResult Add(ContactViewModel viewModel)
{
var contact = new Contact();
contact.Name = viewModel.Name;
contact.Surname = viewModel.Surname;
contact.CellNumber = viewModel.CellNumber;
service.Add(contact);
return RedirectToAction("Index");
}
Which I think is a lot neater (plus no magic strings). I find that this approach is much easier to test and maintain.
Keep in mind that you can even create your own model binder for specifying how the form values should bind to the view model. (More on this in a later post). However in most cases the default model binder should be sufficient.
Happy coding.
How do you handle the Identity of the record being updated when doing Edit commands?
How would you handle it using the FormCollection class?
I don't know if I understand your question correctly, but I would add an Id (and possibly Timestamp) field to the ViewModel and then set these as hidden fields in the HTML form. Does that answer your question?