Опубликован: 24.05.2010 | Уровень: специалист | Доступ: платный
Лекция 5:

Технология ASP.Net: основы, создание сложных веб - страниц

Обратим ваше внимание на то, что здесь и в дальнейшем будет идти речь о ASP.NET версии 3.5, тем не менее все нижеследующее в равной степени справедливо и для версии ASP.NET 2.0

ASP.NET — технология создания веб-приложений и веб-сервисов от компании Майкрософт. Она является составной частью платформы Microsoft .NET и развитием более старой технологии Microsoft ASP.

ASP.NET – технология, используемая для написания мощных клиент-серверных интернет приложений. Она позволяет создавать динамические страницы HTML.

Как правило, под динамическими страницами понимают страницы, которые перед отправкой клиенту проходят цикл обработки на стороне сервера.

ASP.NET содержит множество готовых элементов управления, используя которые можно быстро создавать интерактивные web-сайты.

Microsoft .NET Framework - это платформа для создания, развертывания и запуска Web-сервисов и приложений. Она предоставляет высокопроизводительную, основанную на стандартах, многоязыковую среду, которая позволяет интегрировать существующие приложения с приложениями и сервисами следующего поколения, а также решать задачи развертывания и использования Интернет - приложений.

.NET Framework состоит из трех основных частей: общеязыковой среды выполнения (common language runtime), иерархического множества унифицированных библиотек классов и компонентной версии ASP, называемую ASP.NET.

Структура страниц ASP.NET

Типичная веб-страница состоит из трех секций: директивы страницы, код и разметка страницы. Эти секции описаны ниже.

  • Директивы страницы

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

  • Код

    Эта секция содержит код для обработки событий, генерируемых страницей или ее элементами управления. Код дозволяется размещать в тэге <script>. По умолчанию блоки сценария содержат код, выполняющийся на клиенте, но можно объявлять их и как серверный код, включив в тег <script> атрибут runat="server". Код также может содержаться в прикрепленных файлах, называемых файлами отделенного кода ( code-behind ). Весь код страницы компилируется перед выполнением. Кроме того, все страницы допускается предварительно скомпилировать в сборку (если сборка — единственный файл, предназначенный для развертывания).

  • Разметка страницы

    Разметка страницы — это HTML-код страницы, включающий HTML-тэг body и его содержимое. Там же размещаются клиентские и серверные элементы управления, а также простой текст.

Динамическая компиляция веб-сайта

В ASP.NET реализована модель динамической компиляции веб-сайтов. В этом приложении код не компилируется до вызова пользователем, работающим с сайтом. Если применяется динамическая компиляция, то Visual Studio не создает исполняемую сборку, пригодную для развертывания, а компилирует страницы по запросу пользователя. Компиляция страницы зависит от временной отметки файла исходного кода. Если исходный код изменился, страница перекомпилируется при следующем запросе. Динамическая компиляция имеет такие преимущества:

  • не нужно заново компилировать все приложение после каждого изменения в одной странице или в одном компоненте, что наиболее ценится разработчиками крупных веб - сайтов и порталов;
  • страницы, при компиляции которых возникают ошибки, не мешают работе других страниц веб-сайта. Эта своеобразная "независимость" одних страниц от других позволяет в рамках одного решения одновременно использовать одни страницы, тестировать другие и разрабатывать третьи.

При создании веб-сайта Visual Studio 2008 не проверяет, все ли страницы и их зависимости компилируются. Для запуска веб-сайта не создается сборка, Visual Studio 2008 проверяет, можно ли скомпилировать код, и ищет синтаксические ошибки в разметке и файле Web.conflg.

Компиляция в ASP.NET

Чтобы код приложения обрабатывал запросы пользователей, платформе ASP.NET необходимо вначале скомпилировать код в одну или несколько сборок.

Сборка — это файл с расширением DLL.

Код ASP.NET можно писать на самых различных языках, например Visual Basic, C#, J# и других. При компиляции код переводится в независимое от языка и процессора представление, которое называется языком MSIL. Во время работы MSIL выполняется в контексте платформы .NET Framework, которая переводит MSIL в индивидуальные инструкции для процессора компьютера, на котором запущено приложение.

Преимущества компиляции:

  • Производительность . Скомпилированный код функционирует гораздо быстрее таких языков сценариев, как ECMAScript или VBScript, поскольку его представление ближе к машинному коду и не требует дополнительного анализа.
  • Безопасность. Скомпилированный код гораздо сложнее реконструировать, чем нескомпилированный исходный код, так как он не обладает легкостью чтения и абстрактностью языков высокого уровня. Кроме того, существуют средства запутывания кода, которые делают скомпилированный код еще более устойчивым к реконструированию.
  • Стабильность. Во время компиляции код проверяется на наличие ошибок, строгость типизации и наличие прочих проблем. Обнаружение этих ошибок на этапе построения позволяет исключить множество ошибок в коде.
  • Взаимодействие. Благодаря тому, что код MSIL поддерживает любой язык .NET, можно использовать сборки, которые изначально были написаны в коде на других языках. Например, если веб-страница ASP.NET пишется на языке C#, то можно добавить в нее ссылку на файл DLL, который был написан на языке Visual Basic.

Жизненный цикл страницы

Жизненный цикл страницы ASP.NET начинается с получения и обработки Web-сервером IIS запроса к данной странице и передачи этого запроса среде выполнения ASP.NET. В момент получения запроса, среда выполнения загружает класс вызываемой страницы, устанавливает свойства класса страницы, выстраивает дерево элементов, заполняет свойства Request и Response и вызывает метод HttpHandler.ProcessRequest. После этого среда выполнения проверяет каким образом была вызвана эта страница и если страница вызвана путем передачи данных с другой страницы , то среда выполнения устанавливает свойство PreviousPage.

Этап Описание
Запрос станицы Запрос страницы осуществляется до начала жизненного цикла страницы. Когда пользователь осуществляет запрос, среда выполнения ASP.NET устанавливает, необходимо ли осуществить компиляцию (в случае изменения исходного кода) страницы и начать жизненный цикл, либо можно выдать в качестве ответа страницу из кеша.
Начало жизненного цикла На этом этапе происходит установка свойств Response и Request и свойства UICulture. Также, на этом этапе устанавливается свойство IsPostBack. IsPostBack - данное свойство возвращает значение, указывающее, загружается ли страница в ответ на обратный запрос клиента, или же доступ к ней осуществляется впервые
Инициализация страницы Ко времени инициализации страницы все дочерние пользовательские элементы управления уже созданы и имеют установленные свойства UniqueID. В это же время к странице применяются темы оформления. Если страница вызвна в результате постбэка, то данные, отправленные на сервер, еще не загружены в свойства элементов управления, на этом этапе.
Загрузка Если страница вызвана в результате постбэка, то на этом этапе устанавливаются свойства элементов управления, на основании информации о состоянии ( ViewState и ControlState ).
Валидация Вызывается метод Validate() для всех, находящихся на странице проверочных элементов управления.
Обработка постбэка Вызываются обработчики событий (при условии, что постбэк произошел).
Рендеринг Сохраняется информация о состоянии, затем класс страницы вызывает соответствующие методы дочерних элементов управления для генерации HTML представления и передачи его в Response.OutputStream.
Выгрузка Выгрузка происходит после того, как создано HTML представление для всей страницы.

Обработчики и модули HTTP

Обработчик HTTP — это компонент, на который возложена ответственность за обслуживание запроса. Он представляет собой экземпляр класса, реализующего интерфейс IHttpHandler. Метод ProcessRequest этого интерфейса является центральной консолью, управляющей обработкой запроса. Например, класс Pageбазовый класс, производными от которого являются все страницы ASP.NET времени выполнения, — реализует интерфейс IHttpHandler, метод ProcessRequest которого отвечает за загрузку и сохранение состояния просмотра, а также за генерирование событий, таких как Init, Load, PreRender и им подобных.

ASP.NET отображает каждый входящий HTTP-запрос на конкретный обработчик HTTP. Компонент особого рода, называемый фабрикой обработчиков HTTP (HTTP handler factory), предоставляет инфраструктуру для создания физического экземпляра обработчика, который будет обслуживать запрос. Например, класс PageHandlerFactory анализирует исходный код запрошенного ресурса .aspx и возвращает откомпилированный экземпляр класса, представляющего страницу. Обработчик HTTP предназначен для обработки одного или нескольких расширений URL. Областью действия обработчика может быть конкретное приложение или весь компьютер, то есть он может обрабатывать файлы с назначенными ему расширениями в контексте либо текущего приложения, либо всех приложений, установленных на компьютере. Назначение обработчику области действия осуществляется путем внесения изменений в глобальный файл machine.config или локальный файл web.config, в зависимости от того, какую область действия вы выбираете.

Модули HTTP — это классы, реализующие интерфейс IHttpModule и обрабатывающие события времени выполнения, т.е. позволяют проверять входящие и исходящие запросы и выполнять определенные действия на их основе. Данный модуль представляет собой сборку, вызываемую по каждому запросу к приложению.

Существует два типа событий, с которыми может иметь дело такой HTTP - модуль. Это события, генерируемые объектом HttpApplication (в том числе асинхронные), и события, генерируемые другими модулями HTTP. Например, SessionStateModule — это один из встроенных модулей ASP.NET, предоставляющих приложениям сервисы, связанные с состоянием сеанса. Модуль SessionStateModule генерирует события End и Start, которые могут обрабатываться другими модулями с использованием общеизвестных сигнатур Session_End и Session_Start.

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

Создание сложных страниц. Асинхронные страницы.

Каждый входящий запрос ASP.NET назначается потоку, выбранному из пула потоков ASP.NET. Этот запрос обслуживается обработчиком HTTP, выбираемым с учетом типа запроса и установок, заданных в файле web.config. Обработчик HTTP — это регистрируемый объект, реализующий интерфейс IHttpHandler, и в частности метод ProcessRequest, который, собственно, и отвечает за выполнение запроса. Упомянутый поток вызывает метод ProcessRequest обработчика и ждет завершения его выполнения. Как долго?

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

Единственным выходом из этой трясины является "применение асинхронных обработчиков.

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

Типичными примерами операций, в которых задействуются преимущественно устройства ввода-вывода, являются доступ к удаленным источникам данных и взаимодействие с внешними устройствами.

Реализация асинхронной страницы

Все начинается с установки атрибута Async директивы @Page. Если этот атрибут установлен, то динамически генерируемый класс страницы будет реализовывать интерфейс IHttpAsyncHandler. Атрибут AsyncTimeout указывает максимальное количество времени в секундах, отведенное на выполнение асинхронных операций.

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" 
Inherits="_Default" Async="true" AsyncTimeout="35" %>

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

  1. Метод AddOnPreRenderCompleteAsync
    public void AddOnPreRenderCompleteAsync(BeginEventHandler beginHandler, EndEventHandler endHandler);

    Метод AddOnPreRenderCompleteAsync вызывается в обработчике события Load страницы и предназначен для регистрации двух обработчиков начала и конца асинхронной обработки.

    protected void Page_Load(object sender, EventArgs e)
    {
        AddOnPreRenderCompleteAsync(new BeginEventHandler(BeginAsync), new EndEventHandler(EndAsync));
    }

    Метод BeginAsync вызывается средой выполнения ASP.NET после события PreRender и задача этого метода в том, чтобы начать асинхронную операцию.

    public IAsyncResult BeginAsync(object sender, EventArgs e, AsyncCallback callback, object state)
    {
      ds = new localhost.DataService();
      ds.Url = new Uri(Request.Url, "WebServices/DataService.asmx").ToString();
      return ds.BeginGetLoginNames(callback, state);

    При этом нить, использованная для обработки запроса, возвращается в пул нитей. После завершения асинхронной операции (при условии, что не происходит тайм-аут) из пула нитей извлекается нить, вызывается метод EndAsync, происходит событие PreRenderComplete и продолжается обработка запроса.

    public void EndAsync(IAsyncResult asyncResult)
    {
      string res = ds.EndGetLoginNames(asyncResult);
      string[] users = res.Split('\n');
      for (int i = 0; i < users.Length; i++ )
      {
        string[] user = users[i].Split(':');
        if(user.Length == 3)
          phNames.Controls.Add(new LiteralControl("<p><b>" + user[1] + "</b> ID: " + 
                                         user[0] + " Name: " + user[2] + "</p>"));
      }
    }
  2. Метод RegisterAsyncTask
    public void RegisterAsyncTask(PageAsyncTask task);

    Метод RegisterAsyncTask используется, если необходимо провести более одной асинхронной операции. Более того, RegisterAsyncTask позволяет установить обработчик, который будет вызван если асинхронная операция не уложится по времени в установленное атрибутом AsyncTimeout время, а также позволяет передать в делегат, используемый для реализации асинхронного вызова сведения о состояния и указать, может ли задача выполнятся параллельно с другими поставленными в очередь асинхронными задачами. В случае, когда указанное выше не требуется, можно использовать AddOnPreRenderCompleteAsync и избежать написания лишнего кода.

    PageAsyncTask task1 = new PageAsyncTask(new BeginEventHandler(BeginAsyncText), 
    new EndEventHandler(EndAsyncText), 
    new EndEventHandler(Async_OnTimeout), null);
    PageAsyncTask task2 = new PageAsyncTask(new BeginEventHandler(BeginAsyncDS), 
    new EndEventHandler(EndAsyncDS), 
    new EndEventHandler(Async_OnTimeout), null);
    RegisterAsyncTask(task1);
    RegisterAsyncTask(task2);

Жизненный цикл асинхронной страницы

  • Объект HttpRuntime принимает запрос и вызывает метод BeginProcessRequest обработчика асинхронной страницы. Выполнение операции начинается в рабочем потоке из пула ASP.NET. Сигналом о завершении операции служит обратный вызов.
  • Рабочий поток выполняет страницу в синхронном режиме до асинхронной точки. При этом, как обычно, генерируются события вплоть до PreRender включительно.
  • По достижении асинхронной точки начинается выполнение асинхронного задания и инициируются операции ввода-вывода. Обработчик Begin возвращает объект, реализующий IAsyncResult.В состав этого объекта входит функция обратного вызова, которая будет вызвана, когда выполнение асинхронного задания завершится.
  • Рабочий поток, обслуживающий запрос, возвращается в пул, хотя асинхронная операция продолжается. На это время ни один поток не блокируется.
  • Когда асинхронное задание выполнено, вызывается функция обратного вызова, которая в свою очередь вызывает обработчик End, и в выходной поток страницы выводятся результаты обратного вызова. Эта работа обычно выполняется в потоке, выбранном из пула потоков завершения.
  • Функция обратного вызова ставит в очередь "второй частичный запрос". Но на этот раз булевы аргументы имеют противоположные значения и выполняется этап, следующий за асинхронной точкой. Выполнение исходного запроса завершается, и управление возвращается объекту HttpRuntime.
  • Объект HttpRuntime вызывает метод EndProcessRequest асинхронного обработчика страницы. Этот обработчик проделывает небольшую работу и генерирует исключение, если в ходе нее происходит ошибка.
  • На этом функции обработчика завершаются, и исполняющая среда HTTP выводит ответ, после чего генерирует обычную последовательность событий уровня приложения вплоть до EndRequest.

Список использованных источников

  1. http://www.aspnetmania.com/Articles/Article/75.html
  2. http://www.cyberguru.ru/dotnet/asp-net/asp-net-2-intro-page5.html
  3. http://msdn.microsoft.com/ru-ru/library/bb398986.aspx