Why will <%= %> expressions as property val

2019-01-02 18:36发布

问题:

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?

回答1:

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.



标签: