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

Программирование уровня приложения ASP.NET

Показывать лекцию целиком
Файлы к лекции Вы можете скачать здесь

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

Исполняемое средой ASP.NET приложение называется доменом (по аналогии с процессом при исполнении приложения локального стола). В отличие от локальных приложений, конечный пользователь никогда не запускает приложение ASP.NET напрямую. Он запускает броузер на своем локальном компьютере и запрашивает определенный URL. Этот запрос получет Web-сервер и передает его среде исполнения ASP.NET (рабочему процессу), которая выделяет в памяти домен для виртуального каталога и загружает в него код адресуемой страницы. Таким образом, домен приложения создается рабочим процессом при первом запросе любой страницы или Web-службы виртуального каталога.

Web-страницы и Web-службы одного виртуального каталога выполняются в одном и том же домене. Содержимое другого виртуального каталога выполняется в своем домене. Выполнение приложений из разных виртуальных каталогов в отдельных изолированных доменах гарантирует, что одно приложение не сможет оказывать влияние на работу другого, в том числе видеть его данные, хранящиеся в оперативной памяти. За этим строго следит общеязыковая среда выполнения CLR.

Все Web-страницы или Web-службы совместно используют одни и те же ресурсы, которые недоступны другим приложениям. Конфигурационные настройки среды исполнения, помещенные в файл Web.config виртуального каталога приложения, действуют только в пределах этого приложения. Страницы, требующие еще более индивидуальных настроек, могут быть помещены в подкаталоги со своими файлами Web.config.

Приложение может состоять из следующих компонентов:

  • Web-страницы (файлы .aspx) - основные рабочие единицы любого приложения
  • Web-службы (файлы .asmx) - выполняют полезную работу для сторонних приложений
  • Файлы отделенного кода (.cs) - содержат исполнимый код для программного управления объектами, определяемыми в интерфейсной части страницы
  • Конфигурационные файлы (Web.config) - содержат настройки среды исполнения (рабочего процесса) как для всего приложения в целом, так и для групп страниц, расположенных в подкаталогах виртуального каталога
  • Файл событий приложения (Global.asax) - содержит обработчики событий, которые реагируют на глобальные события самого приложения
  • Другие компоненты: базы данных, пользовательские элементы управления, отдельные сборки, каскадные таблицы стилей, рисунки, XML-файлы и т.д.
  • ASP.NET периодически перезапускает приложение в другом домене для освобождения неиспользуемых ресурсов (говорят, что приложение переходит в новый домен ). При этом старый домен будет работать до тех пор, пока не будут обработаны все запросы клиентов, стоящие в очереди. То же самое происходит и при замене разработчиком содержимого страниц и конфигурационных файлов. Среда обнаруживает новые изменения, создает для модифицированного приложения новую сборку и запускает ее в новом домене, выполняя его одновременно со старым немодифицированным. Из-за того, что CLR всегда блокирует файлы сборок при выполнении приложения, перед созданием нового домена она автоматически создает для него копии файлов сборок в каталоге

    C:\[Каталог_Windows]\Microsoft.NET\[Версия]\Temporary ASP.NET Files

    При создании домена приложение может создавать в нем не один экземпляр объектов приложения, а целый пул, содержащий от 1 до 100 экземпляров, в зависимости от масштабируемости (количества) запросов. Каждый новый запрос от одного и того же клиента может адресоваться к разным экземплярам пула домена.

    Файл приложения Global.asax

    Файл Global.asax является необязательным для приложения. Но если он присутствует, то должен быть единственным и находиться в корне виртуального каталога приложения. Этот файл включает в себя обработчики событий уровня приложения, которые выполняются автоматически в ответ на происходящие с приложением события. Код обработчиков пишется точно также, как и исполняемый C#-код обычной страницы .aspx и не должен содержать никаких дескрипторов.

    Любое приложение является экземпляром класса, наследующего класс HttpApplication. Код файла Global.asax является неявным расширением этого базового класса и будет иметь доступ ко всем его свойствам и методам. В этом файле мы можем заполнить заготовки методов с предопределенными именами, а также создать обработчики на интересующие нас события уровня приложения. Все они должны иметь одинаковую сигнатуру, определенную делегатом

    public delegate void System.EventHandler(object sender, System.EventArgs e)

    Заготовки методов класса приложения с предопределенными именами

    Объект приложения создается автоматически, поэтому мы не можем сами регистрировать некоторые обработчики, присваивая им произвольные имена. Как и в случае с экземпляром класса Page, мы можем использовать только предопределенные имена обработчиков приложения.

    Базовый класс HttpApplication имеет ряд событий, которые срабатывают при определенных условиях и в определенной последовательности. Большая часть этих событий связана с запросом. На любое из них мы можем подписаться в методе Application_Start() и создать обработчик с произвольным именем, либо воспользоваться именами по умолчанию Application_ИмяСобытия. В таблице приведены примеры обработчиков событий приложения и сеанса, а также обработчики событий, связанных с запросами:

    Некоторые обработчики уровня приложения
    Обработчик Описание
    Обработчики событий приложения и сеанса
    Application_Start() Этот метод вызывается тогда, когда впервые запускается приложение и создается домен. В этом обработчике удобно инициализировать такие данные, как деревья навигации, общие счетчики и др.
    Application_End() Вызывается сразу после завершения работы приложения. Приложение может завершить работу вследствии перезапуска IIS или перехода в новый домен из-за обновления файлов виртуального каталога
    Application_Error() Вызывается всякий раз, когда в приложении возникает необработанное событие
    Session_Start() Вызывается всякий раз, когда в приложении начинается новый сеанс. Удобен для инициализации информации, специфичной для конечного пользователя
    Session_End() Вызывается всякий раз при завершении сеанса. Сеанс завершается, когда мы явно освобождаем его в коде, или если сеанс простоял заданное время (обычно 20 минут), не получив ни одного запроса. Используется для очистки любых связанных данных
    Обработчики событий, связанных с запросами
    Application_BeginRequest() Вызывается в начале каждого запроса, включая запросы на файлы, не являющиеся Web-формами (например, Web-службы)
    Application_AuthenticateRequest() Вызывается до начала аутентификации (распознавания пользователя). Сюда можно поместить собственную логику аутентификации
    Application_AuthorizeRequest() Вызывается после выполнения аутентификации для назначения специальных прав
    Application_ResolveRequestCache() Используется вместе с кэшированием выходных данных
    Application_AcquireRequestState() Срабатывает после извлечения из запроса информации о пользователе перед сохранением ее в коллекции сеанса
    Application_PreRequestHandlerExecute() Вызывается перед тем, как будет выполнен запрос и сгенерируется HTML-код обработчиками страницы
    Application_PostRequestHandlerExecute() Вызывается после обработки запроса
    Application_ReleaseRequestState() Вызывается тогда, когда информация сеанса сериализуется из коллекции Session, чтобы стать доступной в следующем запросе
    Application_UpdateRequestCache() Вызывается перед добавлением информации в кэш выходных данных, если он был разрешен
    Application_EndRequest() Вызывается в конце запроса и используется для размещения кода очистки

    Демонстрация событий приложения

    Приведем пример, иллюстрирующий работу рассмотренных методов уровня приложения.

  • Создайте новый пустой проект с помощью команды File/New/Web Site/Empty Web Site
  • Добавьте к проекту командой Website/Add New Item/Web Form новую страницу Default.aspx без файла отделенного кода и модифицируйте ее так
    (рис ) Модифицированная страница Default.aspx<%@ Page Language="C#" %>
  • Добавьте к проекту файл Web.config командой Website/Add New Item/Web Configuration File с включенной опцией отладки, чтобы его код был таким
    (рис ) Конфигурационный файл с включенной опцией отладки<?xml version="1.0"?>
    <configuration>
    	<system.web>
    		<compilation debug="true"/>
    	</system.web>
    </configuration>
  • Добавьте к проекту файл Global.asax, выполнив команду Website/Add New Item/Global Application Class, и заполните его следующим кодом
    (рис ) Код файла Global.asax<%@ Application Language="C#" %>
        
    <script runat="server">
        
        //************************************************************************
        //******************** Обработчики событий приложения ********************
        //************************************************************************
        
        void Application_Start(object sender, EventArgs e) 
        {
            //HttpApplication Application = new HttpApplication();
                
            System.Diagnostics.Debug.WriteLine(
                "************Application_Start*********");
        }
        
        void Application_End(object sender, EventArgs e) 
        {
            System.Diagnostics.Debug.WriteLine(
                "************Application_End*********");
        }
            
        void Application_Error(object sender, EventArgs e) 
        { 
            System.Diagnostics.Debug.WriteLine(
                "************Application_Error*********");
        }
        
        void Session_Start(object sender, EventArgs e) 
        {
            System.Diagnostics.Debug.WriteLine(
                "************Session_Start*********");
        }
        
        void Session_End(object sender, EventArgs e) 
        {
            System.Diagnostics.Debug.WriteLine(
                "************Session_End*********"); 
        }
        
        //************************************************************************
        //******************** Обработчики событий запроса ***********************
        //************************************************************************
        
        void Application_BeginRequest(object sender, EventArgs e)
        {
            Response.Write("<ol>\n");
            Response.Write("<li>Application_BeginRequest\n");
        }
        
        void Application_AuthenticateRequest(object sender, EventArgs e)
        {
            Response.Write("<li>Application_AuthenticateRequest\n");
        }
        
        void Application_AuthorizeRequest(object sender, EventArgs e)
        {
            Response.Write("<li>Application_AuthorizeRequest\n");
        }
        
        void Application_ResolveRequestCache(object sender, EventArgs e)
        {
            Response.Write("<li>Application_ResolveRequestCache\n");
        }
        
        void Application_AcquireRequestState(object sender, EventArgs e)
        {
            Response.Write("<li>Application_AcquireRequestState\n");
        }
        
        void Application_PreRequestHandlerExecute(object sender, EventArgs e)
        {
            Response.Write("<li>Application_PreRequestHandlerExecute\n");
        }
        
        void Application_PostRequestHandlerExecute(object sender, EventArgs e)
        {
            Response.Write("<li>Application_PostRequestHandlerExecute\n");
        }
        
        void Application_ReleaseRequestState(object sender, EventArgs e)
        {
            Response.Write("<li>Application_ReleaseRequestState\n");
        }
        
        void Application_UpdateRequestCache(object sender, EventArgs e)
        {
            Response.Write("<li>Application_UpdateRequestCache\n");
        }
        
        void Application_EndRequest(object sender, EventArgs e)
        {
            Response.Write("<li>Application_EndRequest\n");
            Response.Write("</ol>\n");
        }
        
    </script>
  • Выполните приложение и в окне броузера должен появиться следующий результат
  • Application_BeginRequest
  • Application_AuthenticateRequest
  • Application_AuthorizeRequest
  • Application_ResolveRequestCache
  • Application_AcquireRequestState
  • Application_PreRequestHandlerExecute
  • Application_PostRequestHandlerExecute
  • Application_ReleaseRequestState
  • Application_UpdateRequestCache
  • Application_EndRequest
  • В панели задач щелкните дважды на иконке тестового сервера
  • Остановите тестовый сервер щелчком на кнопке
  • Откройте (если его не видно) окно Output оболочки командой View/Output и обратите внимание, что в нем присутствует, в том числе, информация, выдаваемая обработчиками приложения и сеанса, которая будет примерно такой
  • ************Application_Start*********
    'WebDev.WebServer.EXE' (Managed): 
     Loaded  'C:\WINNT\assembly\GAC_MSIL\System.Web.Mobile\2.0.0.0__b03f5f7f11d50a3a\System.Web.Mobile.dll', 
       No symbols loaded.
    'WebDev.WebServer.EXE' (Managed): 
      Loaded 'C:\WINNT\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files\website5x\e0138830\7001bf15\
      App_Web_ayudlfun.dll', Symbols loaded.
    ************Session_Start*********
    'WebDev.WebServer.EXE' (Managed): 
      Loaded 'C:\WINNT\assembly\GAC_MSIL\System.Web.RegularExpressions\2.0.0.0__b03f5f7f11d50a3a\System.Web.RegularExpressions.dll', 
         No symbols loaded.
    ************Session_End*********
    ************Application_End*********
    The program '[1800] WebDev.WebServer.EXE: Managed' has exited with code 0 (0x0).
    The program '[820] IEXPLORE.EXE: Script program' has exited with code 0 (0x0).

    Демонстрация перехвата необработанного события

  • Добавьте к проекту новую страницу Default2.aspx с файлом отделенного кода и назначьте ее стартовой командой Set As Start Page
  • Заполните в застраничном файле обработчик Page_Load() кодом деления на ноль
    protected void Page_Load(object sender, EventArgs e)
    {
        int a=0, b=1;
        int x = b / a;
    }
  • Откройте файл Global.asax, очистите его и скорректируйте так
    (рис ) Содержимое файла Global.asax<%@ Application Language="C#" %>
        
    <script runat="server">
        
        void Application_Error(object sender, EventArgs e) 
        {
            Response.Write("<h1>");
            Response.Write("Произошла какая-то ошибка</h1><hr />");
            Response.Write(Server.GetLastError().Message.ToString());
            Response.Write("<hr />" + Server.GetLastError().ToString());
            Server.ClearError();
        }
        
    </script>
  • Установите в редакторе оболочки страницу Default2.aspx текущей и через контекстное меню выполните для нее команду View in Browser
  • Html-вывод страницы будет таким

    В таком объеме информации трудно разобраться и поэтому обработчик Application_Error() программисты используют только в крайнем случае.

    Вернуться к учебному плану