ASP.NET 4.5 Strongly Typed Data Controls & Model Binding

I’m continuing on these series of articles about what’s new in ASP.NET 4.5.

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.

A typographical error in code

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.  

The code for this article can be downloaded from here.

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

  • http://www.nexustechnologiesllc.com Charles Boyung

    You know you referenced the MVC4 install (and tagged the article with MVC4) in an article that has absolutely nothing to do with MVC, right?

  • Malcolm Sheridan

    @Charles

    It was tagged as MVC4 because I’m continuing on with a series of articles on ASP.NET 4.5 and Studio 2011.

    Yes I am aware it has nothing to do with MVC4, but it’s all ASP.NET 4.5 Studio 2011 goodness.

  • Ben

    I’ve played with ASP.NET 4.5 Web Forms Model Binding, like this but I can’t figure out what the approach for nested binding is. Like for this example putting another GridView inside your GridView’s template. I couldn’t see how to make model binding or strongly typed binding work on the nested gridview. Traditional binding seemed to work but, then I’m backing to finding controls and loading my types. I guess if you only deal with data in a flat fashion in your UI this is great but otherwise not worth much, unless I’m missing something and I hope I am. I did find this project (which I haven’t tried yet) http://webformsmodelbinder.codeplex.com/ on codeplex which looks more promising.

  • Jason

    thanks for sharing this valuable information. Appreciate it!