none
Render не вызывается на master page при асинхронном постбеке RRS feed

  • Вопрос

  • Доброе время суток!

    Имеется следующий мастер:

    <%@ Master Language="C#" AutoEventWireup="true" %>
    
    <script runat="server">
    	protected override void Render (HtmlTextWriter writer)
    	{
    		// this is not called on async postbacks o_O
    		base.Render (writer);
    	}
    </script>
    
    <!DOCTYPE html>
    
    <html>
    <head runat="server">
        <title></title>
    </head>
    <body>
      <form id="form1" runat="server">
        <asp:ScriptManager runat="server"></asp:ScriptManager>
        <asp:ContentPlaceHolder id="ContentPlaceHolder1" runat="server" />
      </form>
    </body>
    </html>

    и страница, его использующая

    <%@ Page Title="" Language="C#" MasterPageFile="~/MasterPage.master" AutoEventWireup="true" %>
    
    <script runat="server">
    	protected override void Render (HtmlTextWriter writer)
    	{
    		// this is called on each postback
    		base.Render (writer);
    	}
    </script>
    
    <asp:Content ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">
    	<asp:UpdatePanel runat="server" UpdateMode="Conditional" ChildrenAsTriggers="false">
    		<ContentTemplate>
    			<asp:Button runat="server" Text="GG1" />
    		</ContentTemplate>
    	</asp:UpdatePanel>
    	<asp:Button ID="Button1" runat="server" Text="GG2" />
    </asp:Content>
    
    

    С удивлением обнаружил, что при нажатии на GG1 метод Render на мастере не вызывается. При обычном постбэке (нажатии на GG2) - все норм. Render на странице вызывается при любом постбэке. Почему так?
    5 марта 2014 г. 17:53

Ответы

  • Ну так при использовании AJAX выполняется частичная отрисовка страницы. Т.е. весь жизненный цикл проходит как обычно, но вот при отрисовке передаётся и рендерится толька изменившаяся часть. А так как в данном случае в мастер странице ничего не меняется – то и отрисовка этой части не происходит. А мастер страница есть не что иное как обычный контрол.

    Сделаем содержимое сообщества лучше, вместе!

    • Предложено в качестве ответа Medet Tleukabiluly 5 марта 2014 г. 19:33
    • Помечено в качестве ответа YatajgaEditor 15 марта 2014 г. 9:24
    5 марта 2014 г. 19:31
    Модератор
  • Не совсем все так, но примерно так и оказалось. В данном случае, рекурсивного вызова внутренних контролов не происходит (иначе бы вызывался метод Render мастера).

    ScriptManager подсовывает свою процедуру Render'a страницы (PageRequestManager.RenderPageCallback) через Page.SetRenderMethodDelegate, что в итоге приводит к тому, что при вызове Page.Render, стандартно вызывается Control.RenderChildrenInternal, где при обычном постбеке вызвался бы метод Render для каждого контрола страницы (а там единственный контрол - это master и есть), а в partial постбеке работает другая ветка, по которой как раз попадаем в PageRequestManager.RenderPageCallback, который, в свою очередь, занимается исключительно рендерингом изменившихся UpdatePanel'ей и прочих вспомогательных скриптов.


    • Изменено Vladimir Zinchenko 6 марта 2014 г. 21:55
    • Помечено в качестве ответа YatajgaEditor 15 марта 2014 г. 9:24
    6 марта 2014 г. 21:54

Все ответы

  • Ну так при использовании AJAX выполняется частичная отрисовка страницы. Т.е. весь жизненный цикл проходит как обычно, но вот при отрисовке передаётся и рендерится толька изменившаяся часть. А так как в данном случае в мастер странице ничего не меняется – то и отрисовка этой части не происходит. А мастер страница есть не что иное как обычный контрол.

    Сделаем содержимое сообщества лучше, вместе!

    • Предложено в качестве ответа Medet Tleukabiluly 5 марта 2014 г. 19:33
    • Помечено в качестве ответа YatajgaEditor 15 марта 2014 г. 9:24
    5 марта 2014 г. 19:31
    Модератор
  • Не так все просто. Можно изменить мастер, чтобы он менялся, Render все равно не будет вызываться, например так:

    <%@ Master Language="C#" AutoEventWireup="true" %>
    
    <script runat="server">
    	protected override void OnPreRender (EventArgs e)
    	{
    		labTime.Text = DateTime.Now.ToLongTimeString ();
    		base.OnPreRender (e);
    	}
    	protected override void Render (HtmlTextWriter writer)
    	{
    		// this is not called on async postbacks o_O
    		base.Render (writer);
    	}
    </script>
    
    <!DOCTYPE html>
    
    <html>
    <head runat="server">
        <title></title>
    </head>
    <body>
      <form id="form1" runat="server">
    		<asp:ScriptManager runat="server"></asp:ScriptManager>
        <asp:ContentPlaceHolder id="ContentPlaceHolder1" runat="server" />
    		<asp:UpdatePanel runat="server">
    			<ContentTemplate>
    				<asp:Label runat="server" ID="labTime" />
    			</ContentTemplate>
    		</asp:UpdatePanel>
      </form>
    </body>
    </html>

    5 марта 2014 г. 19:39
  • Но там же в итоге ничего не меняется, меняется только содержимое панели, не важно, что физически всё это находится в мастер странице. Т.е. при AJAX вызове рендерится только панель. А метод Render  у страницы вызывается потому, что это точка входа в конвейер страницы. Там рекурсивно проходят вызовы внутренних контролов.

    Сделаем содержимое сообщества лучше, вместе!

    6 марта 2014 г. 19:49
    Модератор
  • Не совсем все так, но примерно так и оказалось. В данном случае, рекурсивного вызова внутренних контролов не происходит (иначе бы вызывался метод Render мастера).

    ScriptManager подсовывает свою процедуру Render'a страницы (PageRequestManager.RenderPageCallback) через Page.SetRenderMethodDelegate, что в итоге приводит к тому, что при вызове Page.Render, стандартно вызывается Control.RenderChildrenInternal, где при обычном постбеке вызвался бы метод Render для каждого контрола страницы (а там единственный контрол - это master и есть), а в partial постбеке работает другая ветка, по которой как раз попадаем в PageRequestManager.RenderPageCallback, который, в свою очередь, занимается исключительно рендерингом изменившихся UpdatePanel'ей и прочих вспомогательных скриптов.


    • Изменено Vladimir Zinchenko 6 марта 2014 г. 21:55
    • Помечено в качестве ответа YatajgaEditor 15 марта 2014 г. 9:24
    6 марта 2014 г. 21:54
  • Я постарался описать картину обобщённо, чтобы основной мотив подобной реализации был понятен. Ну а детали реализации вы можете посмотреть, благо весь исходный код уже открыт.

    Сделаем содержимое сообщества лучше, вместе!

    7 марта 2014 г. 6:42
    Модератор