Evaluating The DataBinder

Wednesday, October 20, 2004

I was trying to put together a quick piece of code as an example over the weekend and remembered how much I dislike using DataBinder in ASP.NET.

Let’s say a web service call gives back an array of simple objects (the sort of objects you’d see imported by a web reference):

class Parameter
{  
 public string Name;
 public string Value;
}

I wanted to dump the Parameter array to a web page as easily as possible. The following will not work.

<asp:Repeater id="Repeater1" runat="server">
   <ItemTemplate>
      <tr>
         <td>
            <%# DataBinder.Eval(Container.DataItem, "Name") %>
         </td>
         <td>
            <%# DataBinder.Eval(Container.DataItem, "Value") %>
         </td>
      </tr>
   </ItemTemplate>
</asp:Repeater>

The DataBinder, besides looking awkward, only finds public properties - it doesn’t find public fields. The quick hack to get around this is to replace the language agnostic DataBinder syntax with C# code:

<asp:Repeater id="Repeater1" runat="server">
    <ItemTemplate>
        <tr>
            <td>
                <%# ((Parameter)(Container.DataItem)).Name %>
            </td>
            <td>
                <%# ((Parameter)(Container.DataItem)).Value %>
            </td>
        </tr>
    </ItemTemplate>
</asp:Repeater>

Disadvantages:
There is a huge disadvantage in that if the Parameter class fields ever change, the code in the ASPX won’t generate an error until runtime. It’s also a problem if the ASPX moved from a C# project to a VB.NET project.

Advantages:
To me the second example looks cleaner – I can see an object and a property even through the parentheses of a cast. It’s also blazingly faster - two order of magnitude faster. In fact, in my tests the following:

<%# DataBindParameterName(Container.DataItem) %>
// in the code behind of the class:
protected string DataBindParameterName(object o)
{
    return ((Parameter)o).Name;
}

is still 300x faster than the reflection machinations DataBinder.Eval uses. Food for thought in perf critical scenarios.


Comments
Brett Wednesday, October 20, 2004
That's interesting--I didn't realize DataBinder.Eval performed (relatively speaking) that much slower. What do you use to measure the execution time of a method call like this?
Scott Allen Wednesday, October 20, 2004
In most cases use a high resolution timer (using Google you can find a few).
<br>
<br>For these tests I just used the DateTime class. Like:
<br>
<br>DateTime start = DateTime.Now;
<br>for(int i = 0; i &lt; Int16.MaxValue * 100; i++)
<br>{
<br> string s = DataBinder.Eval
<br> (p, &quot;Name&quot;).ToString();
<br>}
<br>TimeSpan span = DateTime.Now - start;
<br>Console.WriteLine(span.TotalMilliseconds);
<br>
<br>In my I just ran again:
<br>
<br>DataBinder.Eval = 45,000 ms
<br>((Parameter)o).Name = 46 ms
<br>p.GetName(o) = 62 ms
<br>
<br>
Comments are now closed.
by K. Scott Allen K.Scott Allen
My Pluralsight Courses
The Podcast!