Программирование на ASP.NET

Применение серверных элементов управления

Показывать лекцию целиком

Серверные элементы управления можно добавлять к странице как декларативно, так и программно. Но нужно понимать жизненный цикл страницы. Код окна локального приложения Windows остается в памяти компьютера до тех пор, пока пользователь не закроет это окно. Web-страница загружается в память сервера при получении запроса от пользователя. Она анализирует поступившую информацию, генерирует необходимый код, отдает его HTTP и автоматически выгружается из памяти.

Такой порядок существования страницы установлен для экономии ресурсов и масштабируемости (стремления обработать как можно больше пользователей). Он называется жизненным циклом страницы. Жизненный цикл страницы сопровождается рядом знаковых событий, для которых можно создать обработчики. Для динамического добавления элементов управления на страницу нужно знать, в обработчике какого события страница готова принять свои дочерние элементы.

Пример исследования жизненного цикла страницы

Давайте на практике исследуем порядок генерации событий на протяжении жизненного цикла страницы. Названия событий можно получить даже из пустой .aspx -страницы, если включить трассировку в исполняющей среде ASP.NET.

  • Создайте в выбранном каталоге пустой проект Web-приложения
  • В панели Обратите внимание, что мы добавляем страницу с отделенным кодом (включен флажок Place code in separate file ).
  • Запустите добавленную страницу на выполнение щелчком на кнопке Start Debugging.

    Появится окно с предупреждающим сообщением, что для режима отладки нужно создать конфигурационный файл Web.Config с параметром включения отладки

  • Щелкните на кнопке OK и оболочка создаст конфигурационный файл в корневом каталоге проекта

    Автоматически запустится встроенный броузер с пустым рендерингом.

  • Закройте броузер и вновь его запустите командой оболочки File/View in Browser (или одноименной командой контекстного для страницы меню)

    В строке адреса броузера будет примерно следующий текст

    http://localhost:1206/LifeCycleEvents/Default.aspx

  • Замените в строке адреса броузера блок

    Сервер выдаст сообщение об ошибке с предложением внести в конфигурационный файл предлагаемый блок кода

    <configuration>
        <system.web>
            <trace enabled="true"/>
        </system.web>
    </configuration>
  • Скопируйте строку <trace enabled="true"/> параметра, включающего трассировку страниц приложения, и поместите ее в файл Web.Config проекта в секцию <system.web>, где уже находится параметр <compilation debug="true"/>, включающий отладку
  • Запустите приложение и в строке адреса броузера вновь введите вызов страницы Trace.axd
  • Появится страница трассировочных данных, в которой щелчком на гиперссылке View Details (показать подробности) мы получим распечатку трассировки нашей пустой страницы. В секции Trace Information приведен список событий, генерируемых страницей на разных этапах жизненного цикла

    Trace Information
    Category Message From First(s) From Last(s)
    aspx.page Begin PreInit
    aspx.page End PreInit 0,0175430117514936 0,017543
    aspx.page Begin Init 0,0201478120822619 0,002605
    aspx.page End Init 0,0376570206548598 0,017509
    aspx.page Begin InitComplete 0,0381149000780825 0,000458
    aspx.page End InitComplete 0,0400307860356554 0,001916
    aspx.page Begin PreLoad 0,0420332751788286 0,002002
    aspx.page End PreLoad 0,0433926658276401 0,001359
    aspx.page Begin Load 0,043818976992886 0,000426
    aspx.page End Load 0,0499175174498435 0,006099
    aspx.page Begin LoadComplete 0,0503580762359462 0,000441
    aspx.page End LoadComplete 0,0516912065639627 0,001333
    aspx.page Begin PreRender 0,0525765146128907 0,000885
    aspx.page End PreRender 0,0658033353401061 0,013227
    aspx.page Begin PreRenderComplete 0,0682352086647884 0,002432
    aspx.page End PreRenderComplete 0,0701589168455767 0,001924
    aspx.page Begin SaveState 0,164382065318358 0,094223
    aspx.page End SaveState 0,39629729476791 0,231915
    aspx.page Begin SaveStateComplete 0,39674344085631 0,000446
    aspx.page End SaveStateComplete 0,398069307691341 0,001326
    aspx.page Begin Render 0,398760456985455 0,000691
    aspx.page End Render 0,646856234521427 0,248096

    Этот порядок следования события не меняется. Некоторые из них, пока еще страница способна принимать управляющий код, можно перехватить в обработчиках. Давайте для тренировки сделаем это.

    Перехват событий жизненного цикла страницы в обработчиках

  • Измените код разметки страницы Default.aspx, чтобы он выглядел так
    (рис ) Разметочная часть страницы Default<%@ Page Language="C#" AutoEventWireup="true"  
    	 CodeFile="Default.aspx.cs" Inherits="_Default" %>
        
    <html xmlns="http://www.w3.org/1999/xhtml" >
    <head runat="server">
        <title>Untitled Page</title>
    </head>
    <body>
        <form id="form1" runat="server">
            <div id="div1" runat="server">
                <h1 align="center" style="color: Red">
                    Диагностика событий страницы</h1>
            </div>
        </form>
    </body>
    </html>
  • Откройте файл отделенного кода Default.aspx.cs и заполните его так
    (рис ) Кодовая часть страницы Defaultusing System;
        
    public partial class _Default : System.Web.UI.Page 
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            System.Diagnostics.Debug.WriteLine(
                "************Page_Load*********");
            Response.Write("Page_Load<br>\n");
            div1.InnerHtml += "Page_Load<br>\n";
        }
        
        protected void Page_PreLoad(object sender, EventArgs e)
        {
            System.Diagnostics.Debug.WriteLine(
                "************Page_PreLoad*********");
            Response.Write("Page_PreLoad<br>\n");
            div1.InnerHtml += "Page_PreLoad<br>\n";
        }
        
        protected void Page_PreInit(object sender, EventArgs e)
        {
            System.Diagnostics.Debug.WriteLine(
                "************Page_PreInit*********");
            Response.Output.WriteLine("Page_PreInit<br>");
            div1.InnerHtml += "Page_PreInit<br>\n";
        }
        
        protected void Page_Init(object sender, EventArgs e)
        {
            System.Diagnostics.Debug.WriteLine(
                "************Page_Init*********");
            Response.Output.WriteLine("Page_Init<br>");
            div1.InnerHtml += "Page_Init<br>\n";
        }
        
        protected void Page_PreRender(object sender, EventArgs e)
        {
            System.Diagnostics.Debug.WriteLine(
                "************Page_PreRender*********");
            Response.Output.WriteLine("Page_PreRender<br>");
            div1.InnerHtml += "Page_PreRender<br>\n";
        }
        
        protected void Page_Render(object sender, EventArgs e)
        {
            System.Diagnostics.Debug.WriteLine(
                "************Page_Render*********");
            Response.Output.WriteLine("Page_Render<br>");
            div1.InnerHtml += "Page_Render<br>\n";
        }
        
        protected void Page_UnLoad(object sender, EventArgs e)
        {
            System.Diagnostics.Debug.WriteLine(
                "************Page_UnLoad*********");
            //Response.Output.WriteLine("Page_UnLoad<br>");// Поздно, уже все разрушено!
            div1.InnerHtml += "Page_UnLoad<br>";// Поезд ушел, выводим в никуда
        }
    }
  • В каждый обработчик событий жизненного цикла страницы мы включили текстовый вывод в три места:

  • В окно Output оболочки в режиме отладки (вызывается командой меню View/Output
  • В генерируемый отклик страницы впереди разметочной части
  • В разметочную часть страницы динамически добавляем информацию
  • Запустите страницу под управлением оболочки - сгенерируется следующий рендеринг
  • В окне Output оболочки последние строки будут такими

    ************Page_PreInit*********
    ************Page_Init*********
    ************Page_PreLoad*********
    ************Page_Load*********
    ************Page_PreRender*********
    ************Page_UnLoad*********

    Интересно заметить, что код отладки из готовой страницы убирать не нужно. Он автоматически не включается в компиляцию, если из конфигурационного файла убрать параметр <compilation debug="true"/> или выполнить страницу без отладки.

    Страницу без отладки можно запустить напрямую, вызвав броузер через контекстное меню разметочной части страницы командой View in Browser, или выполнив команду оболочки Debug/Start Without Debugging (выполнить без включения отладки). В любом случае среда исполнения ASP.NET перекомпилирует страницу (если были последние изменения в исходном коде по сравнению с DLL) и выполнит ее, направив сгенерированный HTML-код броузеру.

    Динамическое добавление элементов управления

    Приведем пример программного добавления элементов управления на страницу.

  • Командой меню File/New/Web Site создайте новый Web-проект типа ASP.NET Web Site
  • Откройте файл Default.aspx.cs и заполните его следующим кодом
  • using System;
    using System.Data;
    using System.Configuration;
    using System.Collections;
    using System.Web;
    using System.Web.Security;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Web.UI.WebControls.WebParts;
    using System.Web.UI.HtmlControls;
        
    public partial class _Default : System.Web.UI.Page
    {
        // Поля для видимости в методах
        Label lbl1, lbl2;
        TextBox textBox;
        Button btn;
        
        // Свойство для генерации тега <br></br>
        protected HtmlGenericControl BR
        {
            get { return new HtmlGenericControl("br"); }
        }
        
        protected void Page_Load(object sender, EventArgs e)
        {
            lbl1 = new Label();
            lbl2 = new Label();
            textBox = new TextBox();
            // Подписка на событие с регистрацией обработчика
            textBox.TextChanged += new EventHandler(textBox_TextChanged);
            btn = new Button();
        
            form1.Controls.Add(lbl1);
            form1.Controls.Add(BR);
            form1.Controls.Add(lbl2);
            form1.Controls.Add(BR);
            form1.Controls.Add(textBox);
            form1.Controls.Add(BR);
            form1.Controls.Add(btn);
            textBox.Focus();
        
            if (!this.IsPostBack)
            {
                // Настройки при первом запросе,
                // далее сохраняемые в ViewState
                lbl1.Text = "Label";
                lbl1.ToolTip = "Это текстовая метка1";
                lbl2.Text = "Labe2";
                lbl2.ToolTip = "Это текстовая метка2";
                textBox.Style.Value = "color: red; font-style: italic";
                textBox.ToolTip = "Это текстовое поле";
                btn.Text = "Кнопка";
                btn.ToolTip = "Это кнопка Submit";
            }
        }
        
        void textBox_TextChanged(object sender, EventArgs e)
        {
            string str = "<b>" + textBox.Text + "</b>";
            lbl1.Text = str;// Интерпретируемый вывод
            lbl2.Text = HttpUtility.HtmlEncode(str);// Неинтерпретируемый вывод
        }
    }

    Для приема данных из ненадежных источников все дескрипторы нужно превратить в обычные текстовые символы. Для этого применяются два одинаковых метода

  • System.Web.HttpUtility.HtmlEncode(string)
  • System.Web.UI.Page.Server.HtmlEncode(string)
  • Вернуться к учебному плану