Возможности расширения приложений ASP.NET
Обработчики HTTP
HTTP-обработчик – это конечная точка, которая обслуживает запрос к ресурсу. Фактически, HTTP-обработчик содержит код, который запускается для генерации результата для данного типа запросов. Например, ASP.NET Web Forms содержит собственный HTTP-обработчик, который содержит логику генерацию веб-форм. ASP.NET MVC Framework также содержит собственный обработчик, который передает дальнейшее управление внутренним механизмам ASP.NET MVC Framework (таблица маршрутов – контроллер – представление). С точки зрения среды обработки запросов HTTP-обработчик является конечной точкой.
Обычно разработчику веб-приложения не требуется разрабатывать собственные обработчики для страниц и ресурсов приложения – эти обработчики уже доступны в составе той платформы, которая используется на данный момент. Например, класс Page, который является базовым классом для веб-формы является реализацией HTTP-обработчика (реализует интерфейс IHttpHandler). Необходимость в разработке HTTP-обработчика может возникнуть тогда, когда необходимо передать клиенту какой-либо ресурс, который генерируется по собственному алгоритму. Например, можно создать собственный HTTP-обработчик, который передает клиенту изображение, сгенерированное в процессе обработки запроса или полученное из базы данных. В этом случае нет необходимости в использовании сложной цепочки обработки запроса веб-формы.
Как уже говорилось, HTTP-обработчик – это программный компонент, на который возложена ответственность за обслуживание запроса. Он представляет собой экземпляр класса, реализующего интерфейс IHttpHandler. Этот интерфейс содержит логическое свойство IsReusable и метод ProcessRequest.
Свойство IsReusable позволяет определить поведение обработчика при обращении к нему:
- если свойство возвращает значение true, то объект этого класса будет создан при первом обращении к обработчику, после чего этот объект будет использован для обработки всех последующих запросов;
- если свойство возвращает значение false, то объект этого класса будет создаваться каждый раз при обращении к этому обработчику.
С точки зрения производительности приложения и эффективности используемых ресурсов наиболее предпочтительным является первый вариант, при котором один и тот же объект обрабатывает множество запросов. Второй вариант (создание нового объекта для каждого запроса) используется в случае, если объект обработчика хранит внутри себя некоторое состояние.
Метод ProcessRequest является входной точкой для обработки запроса. В нем содержится логика по генерации ответа клиенту. Как видно, этот метод в качестве параметра принимает объект HttpContext. Используя этот объект, можно получить доступ к остальным необходимым для обработки запроса объектам – Request, Response и др. Объект Response позволяет передавать данные клиенту. Для этого можно использовать методы Write, WriteFile и др. Например, для передачи строки пользователю можно использовать следующий код.
Аналогичным образом можно передавать клиенту более сложное содержимое, например, разметку HTML или бинарные данные (изображения, документы и т.д.).
Для реализации собственного HTTP-обработчика можно воспользоваться двумя способами – создать пустой класс и реализовать в нем интерфейс IHttpHandler или воспользоваться встроенным шаблоном в Visual Studio. В последнем случае Visual Studio создает для обработчика также файл с расширением ".ashx". Наличие такого файла позволяет обращаться к нему прямо из браузера. Например, к обработчику с именем MyHandler можно обратиться по адресу "http://…/MyHandler.ashx". Для добавления обработчика в проект подобным образом нужно воспользоваться пунктом меню "Add new item" в Visual Studio и выбрать тип файла "Generic Handler".
При создании HTTP-обработчика этим способом аналогично создается класс, реализующий интерфейс IHttpHandler.
В случае, если HTTP-обработчик создается как обычный класс, не имеющий ассоциированного с ним файла ".ashx", для его использования необходимо задать описание этого обработчика в конфигурационном файле. Для этого используется конфигурационная секция "httpHandlers", которая размещается в секции "system.web". Для добавления нового определения HTTP-обработчика используется узел "add", который содержит следующие атрибуты:
path | задает маску для адреса. Например, можно определить значение этого параметра как "*.test", при этом все запросы к файлам с расширением "test" будут переданы данному обработчику; |
verb | позволяет задать HTTP-методы, которые могут использоваться для обращения к этому обработчику; |
type | задает имя типа (включая пространство имен), которое обрабатывает все запросы. |
Например, определение обработчика в конфигурационном файле может выглядеть следующим образом.
Аналогичным образом, можно определить описания одновременно для нескольких обработчиков.
Если HTTP-обработчик выполняет какую-то длительную вычислительную операцию, то есть смысл реализовать асинхронный HTTP-обработчик. Идея асинхронных обработчиков состоит в том, то для выполнения длительной операции используется новый поток, а основном поток возвращается в пул потоков веб-серверов. После завершения выполнения длительной операции из пула потоков заново изымается основной поток, в рамках которого производится передача обработанной информации клиенту. Для реализации асинхронного обработчика, необходимо создать класс, реализующий интерфейс IHttpAsyncHandler, который содержит два дополнительных метода – BeginProcessRequest и EndProcessRequest. Метод ProcessRequest не используется. Метод BeginProcessRequest запускается для создания нового потока и инициации длительной операции, а второй выполняется после окончания длительной операции и возврата в основной поток. Такой подход позволяет экономить количество потоков в пуле потоков для выполнения длительных операций.
Таким образом, HTTP-обработчики позволяют определить механизм для генерации специфичных данных для пользователя, которые никак не связаны с существующей инфраструктурой генерации страниц ASP.NET.