How ASP.NET databinding deals with Eval() and Bind() statements

A recent question on one of our internal mailing lists asked where the definition for the Bind() method is located in ASP.NET. The asker had located the definition of the Eval() method on the TemplateControl class, but the Bind() method was nowhere to be found, even using Reflector.

If you're familiar with databinding in ASP.NET 2.0, you probably know that for read-only values such as Labels you can use the Eval() statement, and for read-write values such as TextBoxes (also known as "two-way databinding") you can use the Bind() statement. Where does that Bind() statement come from?

To the surprise of many readers, there isn’t a bind method in ASP.NET! When ASP.NET parses your file and sees you're using a databinding expression (in the angle-bracket-percent-pound format, "<%# %>") it has special-case code to parse for the Bind syntax and generates some special code for it. When you use <%# Bind("Name") %> it's not a real function call. If ASP.NET parses the code and detects a Bind() statement, it splits the statement into two parts. The first part is the one-way databinding portion, which ends up being just a regular Eval() call. The second part is the reverse portion, which is typically some code along the lines of "string name = TextBox1.Text" that grabs the value back out from where it was bound.

Non-Bind() databinding statements are literal code (we use CodeSnippetExpressions in CodeDom), so arbitrary code in the language of your choice is allowed. However, because ASP.NET has to parse Bind() statements, two-way databinding doesn’t support anything other than Bind(). For example, the following syntax is invalid because it tries to invoke arbitrary code and use Bind() at the same time:
                <%# FormatNameHelper(Bind("Name")) %>
The only formats supported in two-way databinding are Bind("field") and Bind("field", "format string {0}"). There are some very minor variations of these syntax examples, such as allowing use of single quotes and not just double quotes. Since some languages supported by ASP.NET favor one format over the other, we have to support both formats, even though the language you're using may support only one.

The moral of the story is: There are some things that Reflector won't tell you. smile_teeth

22 Comments

  • I haven't messed with Binding in a while. As I the compiler coudn't tell whether you wrote valid bind statement. Only caught during runtime ala classic asp would the error be caught.

    Has this been fixed now?

  • Hello Eilon, great article and totally relevant to me right now. We have produced an ASP .Net web site using the ASP .Net ObjectDataSource and FormView controls to create our pages.

    We now want to implement a form of data security by determining what the binding is on the control within the FormView and setting the ReadOnly property as applicable.

    However we can find now way of obtaining a reference to the child controls (we can't even get to the controls on Page_Load using FindControl!). We've tried everything to try and obtain the binding text (before it is parsed) of the child controls but to no avail. We started to use a custom FormView control but it started to get complicated so instead created a new set of child controls with a “hint” property containing the name of the element in the data source. I am guessing if we want to create a better solution and interrogate the binding value of the controls we need to write a custom FormView control ?

    Also I have another question, why has it been decided that the binding detail be stored in the text field – why not have a dedicated binding property.

    Many Thanks

  • Dave:
    The ASP.NET parser will tell you whether you have a validly formatted Bind() statement, but it can't (and thus won't) tell you whether the field(s) you are refering to will exist at runtime. In fact, depending on what you're binding against, the list of fields may not be known at all.

    Chris:
    The contents of the databinding expression don't survive beyond the ASP.NET parser. The ASP.NET parser parses those statements and then generates some code and then throws away what it had. There is no parser-related information available at runtime, such as the contents of databinding expressions. Since databinding expressions are completely arbitrary code, I'm not sure what you'd be able to do with it anyway (short of writing a complete parser for every language supported by .NET, which is theoretically infinite...). Granted, it might still be useful if you knew that your target developers only used limited permutations, but unfortunately that is't available.

    Why are the binding expressions in the text field? Well, I do think it's kinda cool that way. "What's the text value? Oh it gets set through the databinding expression right here." However, it of course severely limited the available features due to it being arbitrary code. We've been tinkering with ideas of how we can enhance databinding in ASP.NET but don't have anything ready just yet!

    Thanks,
    Eilon

  • It's pretty much what I'd figured after a day of tinkering (I'm not strictly ASP .Net orientated). Thank you for your prompt and comprehensive response. As for using the text property to hold the binding information for parsing ... I can't say I'm in favour of doing that :)

  • You're not sure what could be done with Binding inforamtion during runtime? First of all, this is false information anyway. The information has to be stored in some form in order for the binder to know what to do with changed data (which controls hold which values and to which field in the data source does the value get saved). I'm trying to extend the FormView so that we can use it for all our web pages. We want to be able to perform operations on data before it is saved back to the datasource, like to dipaly a decimal as a percent (multply x 10) and then dived it back down and store it as it's oprignal decimal format (dive x 10). We also want to the ability to save empty strings as zero and so on. I realize you could do this on each page, but that is ridiculous solution for an app with over 500 pages.

  • Hi Paul,
    You're correct that the information is store somewhere. The point I'm trying to make is that the information is stored in the form of generated code, not a readable data structure.

    So, theoretically, and I mean *very* theoretically, you could get the in-memory IL opcodes and decompile them to figure out which fields are bound to which controls.

    Thanks,
    Eilon

  • Eilon, having difficulties specifying the format string for the Bind method. The following statement doesn’t produce a currency value for a textbox as expected - Text='' – is this a correct implementation of the format string for the Bind method? Thanks

  • Databinding really, really needs to take advantage of the static type-checking possibilities of LINQ.

  • I'm trying to use the Eval method with an application that displays images based on a user's selection. ie when the user clicks on a link, it takes them there, but collects images based on the links destination.

    What I want to do is dynamically show thumbnails of an image dynamically, but give the user the ability to click on it and see if full screen.

    How can I use Eval to dynamically load images not know until runtime?

  • Hi Paul,
    As a guideline for you I'll give you a few pointers as to how we implemented a data security system whereby fields on an ASP .Net form are made hidden or read only. It's a long story but because we had business logic in place before undertaking data security we had to work on the premise that the business layer needed a full set of data to operate on, i.e. without hidden or read only fields. Therefore we had to implement security as late as possible, the best solution we had was to intercept the bind/unbind process from the BL to the UI.

    First we inherited the ObjectDataSource and added event handlers for the Selected and Updating methods. As we deal with DataSets, DataTables or DataRows in the Selected event we check the e.ReturnValue argument and cast it to one of those types. We then save the data to session before manipulating it (i.e. setting fields blank as read only is performed by setting a state on the UI control). In the Updating event we check the session cache for the data and retrieve it merging the non hidden fields with the hidden fields and storing the results in InputParameters. That’s probably all you need to play with.

    Obviously we had to sub class ASP .Net UI controls so that also understood our security model, specifically for the purposes of read only fields. Most of our data binding is quite simple so as previous stated we created a property on each UI control called a binding hint which we interpret and this normally maps back to a property (DataColumn) in the data source. The only work we really have to do is populate the binding hint on each UI control. The control has direct communication to the DataColumns in the DataRow by means of the BindingContainer property on the control (it’s more involved but that’s the basic premise).

    As an aside you might be interested (and you might Eilon) to know how we now use the ObjectDataSource to bind and unbind to our Business Logic (or UI -> BL glue as I prefer to call it). We use strongly typed datasets and have written a small typed dataset generated that basically loads a DataTable with a schema, the schema is output to XML before the XSD.EXE tool is used to generate the class. At the time of generation we pull in some simple home grown templates and via partial classes extend the functionality of the strongly typed set to contain a custom object. The custom object acts as a container class with DataTable and DataRow properties holding the actual data. The custom object has an empty constructor so that the ObjectDataSource can create it. The custom object also has a public property for each DataColumn in the table so that the ObjectDataSource can bind to it. The custom object is then passed into the BL (or BL glue !). This works better for us as we can add and remove fields on the UI without having to alter or create new method signatures in the BL to accept the values from the ObjectDataSource. As a heads up, there was one issue with the custom object mechanism in dealing with dates but we have a work around : )

  • Hey guys, wonder if you can help me with this real quick. I'm trying to do something like this where I set a control to read only based on an eval of another control. Doesn't seem to be working properly, is this possible to eval and compare an expression?

    Here's the code example...

    ReadOnly=''

  • Hi shauntck,
    The code looks like it might almost work. You might have to cast the return value of Eval() to a string first:

    ((string)Eval("audit_status")) == "CLOSED"

    Then you'll also have to call DataBind() on the control with the databinding expression unless someone else is already calling it.

    Thanks,
    Eilon

  • very useful info to know about.
    i was googling for Bind() method just to find here that it doesn;t exist :D.

    Thank you Eilon.

  • Thanks for this information. I was searching for Bind() method in MSDN without any success.

  • Can the Bind() method deal with fields that are complex types? For example, using Bind("Customer.Name") to bind to the Name property of the complex Customer field. This works in the Eval() method, but apparently not in the Bind() method. I can work around it by adding code in the Updating method of the ObjectDataSource, but I would like to see if there is an easier way. Any thoughts?

  • I wish I had known this years ago; it would have saved me a lot of frustration.

    It doesn't look like 3.5 framework even directly supports a call to Bind (?)

    Anyway, thank you for the affirmation that I can wrap around Eval, eg, , it is much appreciated.

  • Hi ,
    Personally I hate this function the most;
    anyone ever tried to use it to get date???
    it gave me an error maybe because of slashes in the date,
    I wasted two days to workin with this **** function.

  • How about binding 2 variables in a linkbutton?

  • Is it possible to use somehow Server or HttpUtility like Server.HtmlEncode(Bind("Pots") for example?

  • can i use bind with if statement. I hv employeetype set to fulltime, parttime, seasonal and none. i need to show some msg based on result of bind.

  • Pls let me knw . i want to eliminate Data Bind() tags inside aspx for runnning fortify tools.
    Shows AntiXSS
    i did for Eval() easily
    this Bind() will throw error..

    i dont want to change more code at ending stage of project

  • i think this is what you are after

    <asp:hyperlink ID="Hyperlink2" runat ="server" NavigateUrl =' & "&Var2=" & Eval("var2")%>'>Click ME

    works perfectly for me when im using it in a list view...most likly works everywhere but i havent tested it

Comments have been disabled for this content.