One pain point that’s dogged WebForm developers for some time is the fact that there haven’t been any strongly typed data controls.  Some of the data controls I’m speaking of include the Repeater, FormView and GridView controls.  They all used templates, which could allow you to specify a view for different operations, such as when you’re editing data compared to adding new data.

When you use these templates today, they’re using late bound expressions to bind the data.  If you’re using the GridView control, or any of the other data controls, you’ll be familiar with the Bind or Eval syntax:

<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="false">
      <Columns>
           <asp:TemplateField HeaderText="Name">
                    <ItemTemplate>
                        <asp:Label ID="lblName" runat="server" Text='<%# Bind("Name") %>'></asp:Label>
                    </ItemTemplate>
                </asp:TemplateField>
                <asp:TemplateField HeaderText="City">
                     <ItemTemplate>
                        <asp:Label ID="lblCity" runat="server" Text='<%# Bind("Address.City") %>'></asp:Label>
                     </ItemTemplate>
                </asp:TemplateField>
      </Columns>
 </asp:GridView>


One of the problems with late-bound data controls is you’re using a string to represent a property name.  If you make a mistake typing the name, you won’t see the exception until runtime.  It’s much better to catch these errors at compile time.  Thankfully Microsoft has addressed this in ASP.NET 4.5 by implementing strongly typed data controls.

Installation

Before starting any development, you’ll need to install ASP.NET 4.5.  The simplest way to do this is via the Web Platform Installer.  All of the ASP.NET 4.5 articles I’m authoring are developed in Visual Studio 2011 Developer Preview. Here’s the link to get started.

Strongly Typed Data Controls

ASP.NET 4.5 introduces strongly typed data controls in the templates.  A new ModelType property has been added to the data controls, and this allows you to specify the type of object that is bound to the control.

Setting this property will add that type to the data controls Intellisense (an autocomplete function), which means no more typing mistakes!  This removes the need to run the website to see if you’ve made any typing mistakes during development.

In this example, I’ve connected to a Northwind web service.  Using ASP.NET 4.5, I can set the ModelType to Northwind.  If the requirement is for one-way data binding, you can use the Item expression.  Bind("Name") becomes Item.Name.  The same goes for the City property.  Replace Bind("Address.City") with Item.Address.City.

<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="false"            ModelType="WebApplication2.NorthwindService.Supplier">
        <Columns>
            <asp:TemplateField HeaderText="Name">
                <ItemTemplate>
                    <asp:Label ID="lblName" runat="server" Text='<%# Item.Name %>'></asp:Label>
                </ItemTemplate>
            </asp:TemplateField>
            <asp:TemplateField HeaderText="City">
                <ItemTemplate>
                    <asp:Label ID="lblCity" runat="server" Text='<%# Item.Address.City %>'></asp:Label>
                </ItemTemplate>
            </asp:TemplateField>
        </Columns>
    </asp:GridView>


For two-way data binding, use Binditem.  So using the example above, data binding to a text box would be like this:

<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="false"            ModelType="WebApplication2.NorthwindService.Supplier">
        <Columns>
            <asp:TemplateField HeaderText="Name">
                <ItemTemplate>
                    <asp:TextBox ID="txtName" runat="server" Text='<%# Binditem.Name %>'></asp:TextBox>
                </ItemTemplate>
            </asp:TemplateField>
            <asp:TemplateField HeaderText="City">
                <ItemTemplate>
                    <asp:TextBox ID="txtCity" runat="server" Text='<%# Binditem.Address.City %>'></asp:TextBox>
                </ItemTemplate>
            </asp:TemplateField>
        </Columns>

    </asp:GridView>

Intellisense is available, so there’ll be no more mistyped properties you only find out about at runtime.

Model Binding

Model binding focuses on coded data access logic.  Previously if you wanted to display data in the GridView control, you either had to explicitly set the DataSource property and call its DataBind method from the code behind.  Like this example:

protected void Page_Load(object sender, EventArgs e)
{
     var products = GetProducts();
     GridView1.DataSource = products;
     GridView1.DataBind();
}

Alternatively you could use one of the many data source controls to bind the data to the GridView.  Now that model binding is part of ASP.NET, you can explicitly tell the GridView which method to call to retrieve its data by using the SelectMethod property.  Here’s the updated GridView.

<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="false"            ModelType="WebApplication2.NorthwindService.Supplier"
            SelectMethod="GetProducts">
        <Columns>
            <asp:TemplateField HeaderText="Name">
                <ItemTemplate>
                    <asp:Label ID="lblName" runat="server" Text='<%# Item.Name %>'></asp:Label>
                </ItemTemplate>
            </asp:TemplateField>
            <asp:TemplateField HeaderText="City">
                <ItemTemplate>
                    <asp:Label ID="lblCity" runat="server" Text='<%# Item.Address.City %>'></asp:Label>
                </ItemTemplate>
            </asp:TemplateField>
        </Columns>
    </asp:GridView>


And in the code behind, here’s the GetProducts method:

public IQueryable<NorthwindService.Supplier> GetProducts()
{
    var service = new NorthwindService.DemoService(new Uri(@"http://services.odata.org/OData/OData.svc/"));
    var suppliers = (from p in service.Suppliers
                             select p);
    return suppliers;
}


This method doesn’t need to be in the code behind. It could live in another class or assembly.  The benefit of returning IQueryable  is that it enables deferred execution on the query, and allows a data-bound control to further modify the query before executing it.  This is useful when you need to implement sorting and paging methods.

I’m excited by the model binding and strongly bound data controls in ASP.NET 4.5.  It has certainly borrowed these ideas and concepts from MVC, so fingers crossed more of them are implemented in upcoming versions