// you’re reading...

Techno-Babble

On WebForms DataBinding

Binding.  I’ve got a lot of feelings about ASP.Net databinding.  Mostly bad.  I think this is part of the reason people wanted to move to MVC.  Databinding, validation, conversion, and persistence are all chained together and ultimately comprise the majority of any application.  Really.  If a platform doesn’t do databinding well, it will probably be abandoned in favor of one that does.

WebForms DataBinding is Deplorable

Webforms does not generally do it well, and the historical MS / WebForms approach assumes you are using datatables and datasets, which is a bit heavy handed of them, as platform designers.   I truly believe that when Ruby on Rails came along and made MVC databinding dead simple (Java Struts wasn’t actually that bad at it either), people finally started to chafe under WebForms.  But we chose WebForms for our new app, and I can back up our rationale (later — not remotely enough time for that now).  But for now let’s just all agree that unless you’re using datatables and datasets, DataBinding is kind of a pain.  How painful is a matter of opinion.  Bottom line: I like WebForms just fine, but the databinding is deplorable and I and my team have spent a good chunk of time coming up with something workable.

Generally this requires an understanding of:
DataSources
DataBoundControls
DataBinding Expressions

I’m not going to explain how these work in this blog entry.  I’m just going to talk about a workaround.

Eval() and Bind()

Eval() and Bind() are crazy.  We all kinda got used to Eval(), but when Bind() came along it threw us for a curve.  It doesn’t work as one would think.  And I’ve never seen any good documentation about how to use it.  Maybe I’ll dig into that a little later.  But then again, it would just be academic, as my most recent development team strongly opposed using binding and datasources.  More on Bind() later.

For now, Eval().

So Eval() is interesting.  It uses reflection (obviously).  This amuses me because this is a complaint people raise about NHibernate and its use of reflection for populating entities, despite the fact that NH basically codegens its own reflection optimizers on the fly.   But ASP.NET uses reflection all over the place.  And, though it’s been a while since I reflected into it, I believe it doesn’t even optimize its reflection.  And that’s kind of understandable, because doing so would be a pain.  But you would think it could do it for repeaters and such.  Maybe it does.  Can’t remember.  Normally I’d check, but since I’m writing this post largely to overcome writer’s block, I’m just going to keep going.

Oh - but the other interesting thing is that the reflection isn’t even really that good.  It doesn’t handle inheritance and interfaces very well at all.  Plus, it’s really not very friendly to refactoring.

Anyway, this brings me to my very simple strategy.

Use binding expressions, but don’t use Eval().

Oh but what to use then?

Use a property.  It’s sooo much better once you get used to it.

Oh wait — I should clarify that I use Domain Objects, rather than DataSets.  If I were to use DataSets, I would use strongly-typed datasets, because

strong typing is good (so are dynamic types, especially when in the same package (i.e. Boo), but more on that later)

That’s just to say, if your Container.DataObject is just some sort of Dictionary, do whatever you please, this technique is certainly not for you.

Back to the technique.  I’m sure your panting with anticipation.

Use Page Properties plus Binding Expressions.

Imagine you’ve got a repeater that does something like


<ItemTemplate>
<tr>
<td><%# Eval("FirstName") %></td>
<td><%# Eval("LastName") %></td>
</tr>
</ItemTemplate>

That’s the standard approach.  Here’s ours:


<ItemTemplate><%# SetCurrentUser(Container.DataItem) %>
<tr>
<td><%# CurrentUser.FirstName %></td>
<td><%# CurrentUser.LastName %></td>
</tr>
</ItemTemplate>

And the code in the code-behind looks like this:


protected User CurrentUser;
protected string SetCurrentUser(object obj) { CurrentUser = (User) obj; return null; }

Now.  That’s a bit unorthodox.  But come on, it’s not that unorthodox.  And it’s so dead simple you can just write a Visual Studio snippet for it.

Note that if you are doing this in a repeater as above, you must use binding expressions rather than scriptlets.  And as I already mentioned, scriptlets are a beating (in WebForms, not in MVC).

Let’s consider the advantages:

  • Strongly typed page properties mean that I get code-completion in my .aspx page.  Ultimately that ends up saving me a lot of time, keystrokes, uncertainty, and is much less error prone.
  • It’s also much more obvious what the code is doing
  • And it doesn’t use reflection at all, which means it performs better.  (Look elsewhere if you want metrics on how much better, but it definitely performs a bit better, especially in large loops like repeaters)

Disadvantages?

  • It uses code-behind, and some people don’t like that.
    • I do.  I can justify it, and will, later
  • I can’t use it for two-way binding.
    • Well, you can’t use Eval for that either.  You have to use Bind()
    • And Bind() does NOT work the way most people think it does.

I’ve never heard of anyone else using this technique.  We just made it up one day.  It works great in our web apps.  What do you think?

More to come on WebForms, Binding, MVC, and lots of other stuff.  I hope.  Actually I’ll just be thrilled if I write another blog entry this year :)

Discussion

No comments for “On WebForms DataBinding”

Post a comment