Почему выражения <% =%> как значения свойств серверных элементов управления приводят к ошибкам компиляции? - PullRequest
50 голосов
/ 16 декабря 2008

Этот вопрос является результатом того, что я заметил, пытаясь ответить на другой вопрос . И теперь мне интересно узнать, почему <asp:TextBox runat="server" Visible="<%= true %>" /> приводит к ошибке компиляции, а не к видимому TextBox, как я ожидал.

Из того, что я обнаружил, выражения <%= %> не переводятся в буквальные элементы управления, как я всегда думал. Но вместо этого он оценивается и записывается непосредственно в HtmlTextWriter при визуализации страницы. Но, очевидно, синтаксический анализатор (я не уверен, что это правильный термин для части, которая переводит разметку ASP.NET в код .NET) даже не пытается оценить выражения <%= %>, когда они используются в качестве значений свойств для сервера управления. Он просто использует его как строку. Я думаю, поэтому я получаю сообщение об ошибке: Невозможно создать объект типа 'System.Boolean' из его строкового представления '<% = true%>' для свойства 'Visible' .

Если я вместо этого выброшу runat = "server" и объединю <%= %> с обычной html-разметкой, например:

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

Затем синтаксический анализатор просто разделяет фрагмент на части до и после выражения, а затем записывает его в HtmlTextWriter в методе рендеринга. Примерно так:

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

Как последнее, что я заметил ... Когда я пытаюсь использовать <%# %> + Control.DataBind (), тогда я получаю то, что ожидал. Он подключает выражение, которое будет использоваться, когда элемент управления привязан к базе данных, но, в отличие от выражения <% =%>, сгенерированный код фактически оценивает содержимое выражения <%# %>. Парсер заканчивает тем, что генерирует следующее:

[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;
}

От:

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

Обратите внимание на button.Visible = true;, который является результатом выражения <%# %>.

Так что мой вопрос ... Почему выражение в первом примере просто обрабатывается как строка, а не оценивается как "true". Выражения несколько похожи для двух других примеров, и они дают код, который я ожидал.

Это просто ошибка (в чем я сомневаюсь, поскольку это не новая проблема с текущей версией ASP.NET), или есть веская причина, почему нам не разрешают использовать <%= %> таким образом?

1 Ответ

94 голосов
/ 16 декабря 2008

Это:

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

Не оценивает это:

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

<% =%> выводится непосредственно в поток ответов, и разметка asp не является частью потока ответов. Ошибочно полагать, что операторы <% =%> выполняют любую предварительную обработку разметки asp.


Кроме того, это помогает подумать о жизненном цикле ASP.NET относительно операторов <% #%> и <% =%>.

  • <% #%> имеет более общую семантику с присвоением значения объекту. В жизненном цикле ASP.NET операторы <% #%> оцениваются до того, как страница записывает первый байт в буфер ответа.

  • <% =%> означает то же самое, что и Response.Write. Сначала нам нужно выполнить всю нашу привязку данных и обработку форм и вывести HTML-код в буфер ответов в самом конце жизненного цикла ASP.NET.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...