This project is read-only.

Model Binder for ASP.NET Web Forms

Bind models to ASP.NET web form controls.

Download the source + sample to get started. The sample is very easy to follow!

Features

  • Two-way model binding (bind model values to controls and vice versa)
  • Supports collection types
  • Supports complex types (nested)
  • Supports native ASP.NET server controls and 3rd party controls (Telerik, Infragistics, etc.)

Usage

Instead of manually binding properties to web forms like this:

        this.FirstName.Text = employee.FirstName;
        this.LastName.Text = employee.LastName;
        this.DateOfBirth.Text = employee.DateOfBirth.ToString();


Bind the model to page controls (Page or User Control) using the ModelBinder:

        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                // Retrieve employee details from the database.
                var employee = GetEmployeeFromDb();

                // Bind the model to page controls.
                ModelBinder.BindControl(employee, this);
            }
        }


Bind the control values to the model:

        protected void Update_Click(object sender, EventArgs e)
        {
            if (Page.IsValid)
            {
                // Bind the control values to model.
                var employee = ModelBinder.BindModel<Employee>(this);

                // Do something like:
                // EmployeeService.UpdateEmployee(employee);
            }
        }

Setting Up (POCO and Attributes)

Attributes:

NotMapped
Properties decorated with the NotMapped attribute will not be binded.

        [NotMapped]
        public string DontBindMe { get; set; }


MapToControl
The control id to bind to. If you don't specify this attribute, the ModelBinder will look for the property name of the class.

        // Look for a control named "txtLastName"
        [MapToControl(ControlId = "txtLastName")]
        public string LastName { get; set; }

        // Look for a control named "FirstName"
        public string FirstName { get; set; }


ValueSource
The control property to bind to (an enum or a string value). If you don't specify this attribute, the default is "Text".

Bind a property to a control with "Text" property

        public string UserCode { get; set; }

        [ValueSource("Text")]
        public string UserCode { get; set; }

        [ValueSource(FromProperty.Text)]
        public string UserCode { get; set; }


Bind the property to a DropDownList

        [ValueSource(FromProperty.SelectedValue)]
        public string ContactPreference { get; set; }


Mapping an int property to an Infragistics WebNumericEditor (DataMode set to "Int")

        [ValueSource("ValueInt")]
        public int Age { get; set; }


A decimal property to an Infragistics WebNumericEditor (DataMode set to "Decimal")

        [ValueSource("ValueDecimal")]
        public decimal Salary { get; set; }


TypeConvert
Instructs the ModelBinder to convert the value. Type conversion is required if you're going to map an integer/decimal/date property to a textbox control.

A decimal property mapped to a Textbox

        // TypeConvert is required because we are mapping a decimal property to a string (Textbox.Text property)
        [ValueSource(FromProperty.Text)]
        [TypeConvert]
        public decimal Salary { get; set; }

        // Using an Infragistic WebNumericEditor, we map the ValueSource to a decimal type so TypeConvert is not needed
        [ValueSource("ValueDecimal")]
        public decimal Salary { get; set; }


Include
Include a complex type in binding (e.g. Address class in Employee). Recursion is supported.

        [Include]
        public Address Address { get; set; }


RaiseBindingError
Instructs the ModelBinder to throw an exception if there's a mapping error (e.g. ValueSource is set to a non-existing property ValueSource("Txt")).

        [RaiseBindingError]
        public class Employee


ValueList
Atttribute to decorate collection types (List<int>, Collection<int>). If you don't specify this value and the property implements the ICollection interface, the ModelBinder will use the default values:
  • CollectionProperty = "Items"
  • SelectedProperty = "Selected"
  • FindMethod = "FindByValue"
  • FindMethodInParent = false
  • AddMethod = "Add"

For ASP.NET controls, you don't need to specify the ValueList attribute for collections. For 3rd party controls like Telerik RadListBox:

        [ValueSource(FromProperty.Value)]
        [TypeConvert]
        [ValueList(FindMethod = "FindItemByValue", FindMethodInParent = true)]
        public Collection<int> Books { get; set; }

Sample

    [RaiseBindingError]
    public class Employee
    {
        [TypeConvert]
        [ValueSource(FromProperty.Value)]
        public int EmployeeId { get; set; }

        public string FirstName { get; set; }

        public string LastName { get; set; }

        [ValueSource(FromProperty.SelectedValue)]
        public string EmployeeType { get; set; }

        [ValueSource(FromProperty.SelectedValue)]
        public string Gender { get; set; }
        
        [TypeConvert]
        public DateTime? DateOfBirth { get; set; }

        [TypeConvert]
        public int NoOfDependants { get; set; }
        
        [ValueSource(FromProperty.Checked)]
        public bool IsActive { get; set; }

        [ValueSource(FromProperty.Value)]
        [TypeConvert]
        public Collection<int> Skills { get; set; }

        [ValueSource(FromProperty.Value)]
        [TypeConvert]
        public Collection<int> Hobbies { get; set; }

        [Include]
        public Address Address { get; set; }
    }

    public class Address
    {
        public string Street { get; set; }

        public string City { get; set; }

        public string StateOrProvince { get; set; }

        [ValueSource(FromProperty.SelectedValue)]
        public string CountryCode { get; set; }

        public string PostalCode { get; set; }
    }

Model Validation

Use Fluent Validation for .NET to validate the model: http://fluentvalidation.codeplex.com/

Last edited Nov 29, 2012 at 2:30 AM by HTT323, version 73