Why will <%= %> expressions as property values on a server-controls lead to a compile errors?
Asked Answered
T

1

54

This question is a result of what i noticed while trying to answer another question. And now im curious to know why <asp:TextBox runat="server" Visible="<%= true %>" /> leads to a compile error, and not to a visible TextBox as i would have expected.

From what i have discovered so far, the <%= %> expressions are not translated to literal controls as i have always thought. But instead it is evaluated and written directly to the HtmlTextWriter when the page is rendered. But apparently the parser (I'm unsure that is the correct term for the part that is translating ASP.NET markup to .NET code) doesn't even attempt to evaluate <%= %> expressions, when they are used as property values for server controls. It just uses it as a string. Which i guess is why I get the error message: Cannot create an object of type 'System.Boolean' from its string representation '<%= true %>' for the 'Visible' property.

If i instead ditch the runat="server" and combines the <%= %> with regular html-markup, like this:

<input type="button" id="Button1" visible='<%= true %>' />

Then the parser just splits the chunk in parts before and after the expression and then writes it to the HtmlTextWriter in the render method. Something like this:

    __w.Write("<input type=\"button\" id=\"Button1\" visible='");
    __w.Write(true);
    __w.Write("' />");

As the last thing i noticed... When i try with <%# %> + Control.DataBind(), then i get what i would expect. It hooks up the expression to be used when the control is databound, but unlike the <%= %> expression, the generated code actually evaluates the content of the <%# %> expression. The parser ends up generating the following:

[DebuggerNonUserCode]
private Button __BuildControldataboundButton()
{
    Button button = new Button();
    base.databoundButton = button;
    button.ApplyStyleSheetSkin(this);
    button.ID = "databoundButton";
    button.DataBinding += new EventHandler(this.__DataBindingdataboundButton);
    return button;
}

public void __DataBindingdataboundButton(object sender, EventArgs e)
{
    Button button = (Button) sender;
    Page bindingContainer = (Page) button.BindingContainer;
    button.Visible = true;
}

From:

<asp:Button ID="databoundButton" Visible='<%# true %>' runat="server" />

Notice the button.Visible = true; that is the result of the <%# %> expression.

So my question is.. Why is the expression in the first example just treated as a string, instead of being evaluated to "true". The expressions is somewhat similar for the two other examples, and they yield the code i would have expected.

Is it just a mistake (which i doubt since it isn't a new issue with the current version of ASP.NET), or is there a good reason why we are not allowed to use <%= %> like that?

Telephotography answered 16/12, 2008 at 0:46 Comment(0)
T
97

This:

<asp:Button runat="server" id="Button1" visible='<%= true %>' />

Does not evaluate to this:

<asp:Button runat="server" id="Button1" visible='true' />

<%= %> outputs directly to the response stream, and the asp markup is not part of the response stream. Its a mistake to assume the <%= %> operators are performing any kind of preprocessing on the asp markup.


As an aside, it helps to think about the ASP.NET lifecycle with respect to the <%# %> and <%= %> operators.

  • <%# %> has semantics more in common with assigning a value to an object. In the ASP.NET lifecycle, the <%# %> operators are evaluated before the page writes the first byte to the response buffer.

  • <%= %> means the same thing as Response.Write. We need to perform all of our databinding and form processing first, and output HTML to the response buffer at the very end of the ASP.NET lifecycle.

Transliterate answered 16/12, 2008 at 1:33 Comment(5)
Thanks, makes good sense, it fits with what i saw in Reflector. I guess i hoped that the "Response.Write"-effect was just a consequence of how i used it, and not the way was made to work.Telephotography
+1 Had to read this answer twice to catch the point: outputs directly to the response stream, and the asp markup is not part of the response stream aka, <%=true%> does not end up in the <asp:Button visible property, but somewhere unrelated!Venerate
You also must call Button1.DataBind() in PageLoad methodIzmir
Or if its easier ( a lot of controls needing DataBind ) call Me.DataBind() to Bind all controls that belong to the page.Itis
Wonder why it doesn't translate attribute="<%:value%>" to be control.Attributes["attribute"]=value in the generated code for the webform/controlFritz

© 2022 - 2024 — McMap. All rights reserved.