ASP.Net MVC Framework 2 - The Binding helper class (UI-mapper)
In this post I’m going to explain the use of the ASP.Net MVC Framework’s BindingHelperExtensions class and how to use it as what I call a UI mapper (map user input fields to an object). The BindingHelperExtensions has the following five methods:
T ReadFromRequest<T>(this Controller controller, String key) string ReadFromRequest(this Controller controller, String key) void UpdateFrom(Object value, NameValueCollection values) void UpdateFrom(Object value, NameValueCollection values, string objectPrefix) void UpdateFrom(Object value, NameValueCollection values, string[] keys)
I will not go deep into the ReadFromRequest method, but they can be used to get a value out from the Request object, such as a QueryString or Form field. They are also extensions method to the Controller class. In this post I will write about the UpdateFrom methods which can be used to easy map a View’s user input fields to an object.
Note: The UpdateFrom methods aren’t extension methods.
The UpdateFrom methods can be used inside of a Controller’s action method to update an object in the Model based on input values. For example if you have a Customer object and want to fill it with values out from the Request.From, you can do the following in your Controller:
Binding.UpdateFrom(customer, Request.Form);
In the examples in this post I will use an alias:
using Binding = System.Web.Mvc.BindingHelperExtensions;
I only use it to avoid using the name of the BindingHelperExtension class to get access to the UpdateFrom methods.
The UpdateFrom will see if there is an input field in the Request.Form collection with the same name as the property of the object passed as an argument. If there is a match, the value from input filed will be set to the value of the object’s property with the same name. For example if you have an input filed like this:
<input type="text" name="CompanyName" .../>
And if the Customer object you pass to the UpdateFrom method has a property with the same name; the value from the CompanyName field will be set to the Customer’s CompanyName property. If you have a View like this:
<input type="text" name="CompanyName" />
<input type="submit" name="City" value="Create"/>
The value of the submit button will be set to the Customer object if it has a property with the name City. So be careful what name you set to the input elements. This can of course be handled by using one of the other two UpdateFrom methods. For example the UpdateFrom that takes a objectPrefix as an argument, can be used to pass in a prefix of the input field names which should be collected from the values argument and be set to the value argument.
void UpdateFrom(Object value, NameValueCollection values, string objectPrefix)
For example if you have input fields that you want to belong to a specific object in the Model, you can use an object prefix like this:
<input type="text" name="Customer.CompanyName" /> <input type="text" name="Customer.ContactName" /> <input type="text" name="Product.Description" />
Note: You can also use "_" to sepereate the prefix from the property name "Customer_CompanyName".
When you use the UdateFrom method and you only want to map the values from the input fields with the prefix Customer to a Customer object passed to the UpdateFrom, you simply pass the “Customer” as an objectPrefix to the UpdateFrom method:
Binding.UpdateFrom(customer, Request.Form, "Customer");
The UpdateFrom will now only collect fields with the prefix “Customer”, and the names after the prefix will be mapped to properties of the Customer object with the same name. By using object prefix you can simply categorize input fields to be mapped to different objects. The last UpdateFrom method you can use is the one that takes an array of keys as an argument.
void UpdateFrom(Object value, NameValueCollection values, string[] keys)
By passing a string array with keys, only the specified keys will be collected from the values argument collection and be set to the value object’s properties. By using keys and pass a Request.Form to the values argument you can decide which input fields you want to collect.
Note: The values argument of the UpdateFrom takes an object of type NameValueCollection, so you pass for example pass the Request.Params collection if you want to get values from both QueryStrings and Forms. You can also pass your own NameValueCollection as you probably already have figured out ;)
To end this post I will give you a simple example how to use the UpdateFrom and with LINQ to SQL to create a new Customer to the Northwind database.
public class CustomerController : Controller { private NorthwindDataContext dbc = new NorthwindDataContext(); public void Index() { RenderView("Customer"); } public void New() { Customer customer = new Customer(); Binding.UpdateFrom(customer, Request.Form, "Customer"); dbc.Customers.InsertOnSubmit(customer); dbc.SubmitChanges(); } }
Customer.aspx
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Customer.aspx.cs" Inherits="MvcUpdateInsertExample.Views.Customer.Customer" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <title></title> </head> <body> <div> <form action="Customer/New" method="post"> Company name: <input type="text" name="Customer.CompanyName" /><br /> Contact name: <input type="text" name="Customer.ContactName" /><br /> <input type="submit" value="Create"/> </form> </div> </body> </html>
I hope this post gave you some brief understanding about how you can use the BindingHelperExtensions class to easy handle user input and map it to an object in the Model.