HTTP Модулі в ASP .NET

Доброго дня. В цій статті ви зможете прочитати інформацію про те, як можна використовуючи засоби ASP .NET написати власний модуль та відразу побачите на прикладі його створення.

Давно я не писав на своєму блозі, так як кілька тижнів відпочивав та навіть встиг побавитись класну гру “Gothic II”, яку я раніше грав і не пройшов до кінця :(.

Для початку потрібно освіжити вашу пам’ять для того, щоб було легше розуміти що таке модуль і для чого він. Для цього я намалював простеньку діаграму, яка показує де саме розміщаються модулі в процесі обробки запиту в ASP .NET:

Мал. 1.1

Як видно з цієї діаграми, в процесі обробки запит проходить кілька етапів, після чого передається до HTTP Хендлера. Коли відповідь сформована, вона повертається до клієнта.

Отже, можна здогадатись, що модулі в ASP .NET дозволяють нам дещо змінити відповідь, або взагалі повністю її переробити.

Може виникнути питання: в яких ситуаціях нам може знадобитись писати власний модуль?

Наприклад на роботі мені дали завдання: зробити просту сторінку, яка буде відображати інформацію про те, що сайт знаходиться в стадії розгортання та відображати її відповідно під час цього процесу. Звичайно я зробив це за допомогою окремого модуля :).

В Visual Studio створіть ASP .NET проект та відразу добавте новий клас з назвою MaintenanceModule.

Щоб цей клас можна було використовувати, потрібно реалізувати інтерфейс IHttpModule:

public class MaintenanceModule : IHttpModule
{
    public void Dispose()
    {
        throw new NotImplementedException();
    }
    public void Init(HttpApplication context)
    {
        throw new NotImplementedException();
    }
}

Як видно з цього коду, потрібно реалізувати лише два методи: Dispose та Init.

В першому методі нам потрібно добавити звільнення від якихось ресурсів: підключення до бази даних, закриття файлу і т.д.. Так як цього в нас немає, я просто залишу його пустим.

В другому ми отримуємо екземпляр класу HttpApplication для того, щоб ми мали змогу якось маніпулювати над відповіддю сервера.

Тепер в Web.config файл добавте одну пару ключ-значення, яка буде зберігатись для визначення теперішнього стану сайту:

<configuration>
  <appSettings>
    <add key="isInMaintenanceMode" value="True"/>
  </appSettings>
  ......
</configuration>

Повернемось до методу Init, який вже є в класі MaintenanceModule. В ньому нам потрібно підписатись до подій, відреагувавши на які ми зможемо модифікувати відповідь сервера. Список подій можна знайти ось тут. В нашому випадку потрібно використати одну – BeginRequest. Модифікуйте метод Init наступним чином:

public void Init(HttpApplication context)
{
    context.BeginRequest += ProcessRequest;
}

Тепер в методі ProcessRequest можна добавляти код для обробки запиту:

private void ProcessRequest(Object sender, EventArgs e)
{
    Boolean isInMaintenanceMode = Boolean.Parse(ConfigurationManager.AppSettings["isInMaintenanceMode"]);
    if (isInMaintenanceMode)
    {
         HttpContext context = HttpContext.Current;
         context.Response.Write("<b>Site is in maintenance mode</b>");
         context.Response.End();
    }
}

Останнім кроком потрібно підключити цей модуль до нашого сайту. Звичайно це робиться в конфігураційному файлі Web.Config:

<configuration>
    <system.web>
      <httpModules>
        <add name="MaintenanceModule" type="CustomModuleSample.MaintenanceModule"/>
      </httpModules>
    <compilation debug="true" targetFramework="4.0" />
    .....
    </system.web>
</configuration>

В реальній ситуації відформатований текст не буде писатись в коді, а буде знаходитись в окремому файлі. Тому змініть код наступним чином:

HttpContext context = HttpContext.Current;
String filePath = context.Server.MapPath("Maintenance.html");
context.Response.WriteFile(filePath);
context.Response.End();

Тепер, якщо в вашому проекті існує файл Maintenance.html, він буде відправлений у відповідь для користувача.

Хотілось би ще додати кілька речень про реалізацію такої самої функціональності, яка використовує Сесію.

Як ви здогадались з назви, подія BeginRequest відбувається на самому початку обробки запиту. В моїй ситуації потрібно було використовувати сесію для того, щоб знати чи зайшов на сайт простий користувач чи адміністратор. Якщо ви спробуєте доступитись до сесії під час цієї події через властивість HttpContext.Session, ви отримаєте виняткову ситуацію (Exception). Тому потрібно підписуватись на подію AcquireRequestState, яка відбувається пізніше, і в якій сесія вже має бути доступною.

Виявилось, що не завжди сесія доступна на цьому етапі. Наприклад якщо від браузера запит пішов не за сторінкою, тоді сесія стає не доступною і знову вилітає ексцепшен.

Це легко виправити добавивши перевірку для об’єкту HttpContext.Handler.

Існують ось такі два інтерфейси: IRequiresSessionState та IReadOnlySessionState, якщо HttpHandlerреалізує перший, то ви можете до неї доступатись та модифікувати. Відповідно якщо тільки другий, то доступ надається тільки для зчитування.

Перевірка може виглядати ось так:

if (context.Handler is IRequiresSessionState || context.Handler is IReadOnlySessionState)
{
    .....
}

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

Як видно, створення власного модуля не є складною задачею, але потрібно завжди думати про те, який код ви туди добавляєте, так як це можна значно погіршити робочу швидкість серверу.

Обов’язково пишіть коментарі до даної статті, якщо ви маєте якісь зауваження до коду або взагалі до реалізації даного прикладу. Всього найкращого 🙂 .

Скачати приклад коду

Advertisements

, , ,

  1. Leave a comment

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: