C# - Saját http modul készítése ASP.NET alkalmazásokhoz

forráskód letöltése
Az ASP.NET alkalmazások felé a felhasználók böngészőjéből érkező kérések áthaladnak meghatározott funkcióval rendelkező „állomásokon”, melyek az adott kérés összetevőit értelmezik, és feldolgozzák. Ebben a cikkben a HttpModule állomást vesszük közelebbről szemügyre egy saját modul elkészítésén keresztül. Az ilyen modulok sok feladatot elláthatnak, melyek implementálásával hasznos elemét képezik az alkalmazásoknak.
Mellékelt példa megnyitása előtt szükséges egy HttpModuleTest nevű virtuális könyvtár létrehozása, mely a példa könyvtárára mutat. Ehhez nyissa meg a mellékelt mappa Tulajdonság ablakát és itt a Webmegosztás lapon engedélyezze a mappa megosztását olvasási és parancsfájlok futtatási jogával.
HTTP-kérés feldolgozása
A megoldás ismertetése előtt vegyük sorra, milyen logikai egységeken halad keresztül egy HTTP-kérés amíg eljut alkalmazásunkig. A példában elkészített modul implementációjához semmilyen módosításra nincs szükség Web-szerverünk konfigurációs beállításaiban.
A kérés első állomása a Web-kiszolgáló szerver szoftvere, jelen esetben az IIS. Az IIS a kérést a kérésből vett információk alapján eljuttatja az ASPNET_ISAPI.dll-hez.
A kérés rögtön továbbítódik az ASP.NET dolgozó-processét reprezentáló ASPNET_WP.exe alkalmazáshoz. A process a kérés fogadása után rögtön készít egy példányt a HTTPContext osztályból, amely beburkolja a kérést.
A kérés csak ezután jut el az adott Web-alkalmazásig, mely a konkrét ASP.NET osztály (például a System.Web.UI.Page osztályból származtatva).
A kérés következő állomása a Http Module nevezetű egység, mely mindent kezel a felhasználói azonosítástól a Session Management-ig. A Web-szerver ISAPI-filterei a Http Module állomás előtt vagy után helyezhetők el. A .NET Framework a IHttpModule interfészt nyújtja megannyi osztállyal a mind tökéletesebb kód elkészítéséhez.
Utolsó állomás egy Http Handler elnevezésű modul, mely feldolgozza a kérést, és generálja a megfelelő választ. A .NET Framework a IHttpHandler interfész osztályait kínálja ezen funkciók elvégzéséhez. Minden ASP.NET alkalmazás, legyen az akár egy .aspx lap, ilyen kezelő segítségével dolgozza fel a kéréseket.
A HttpModule legfőbb jellemzője és előnyös tulajdonsága, hogy a kérés érkezése és kiszolgálása közt eltelt időben az alkalmazáson belül a kéréshez kapcsolódó valamennyi eseményre a modulban kezelőfüggvény valósítható meg, így a kérés lépésről lépésre nyomon követhető. A kapcsolódó események a Web-alkalmazást reprezentáló HttpApplication osztályban vannak deklarálva. Esemény kapcsolható a kérés érkezésének, azonosításának vagy kiszolgálásának pillanatához, így ezekhez tetszőleges eseménykezelő rendelhető a HttpModule egységben.
A http modulok létrehozásakor osztályuk az IHttpModule interfész lehetőségeit implementálja. Az osztályban meg kell valósítani az IHttpModule interfész két metódusát:
Init
Osztály: IHttpModule
void Init(
HttpApplication context
);
A HttpModule inicializálását végző metódus.
Paraméterek
HttpApplication context
Az ASP.NET alkalmazások Application rétegének megvalósulása.
Dispose
Osztály: IHttpModule
void Dispose();
A HttpModule destruktora, mely töröl minden a modul által használt erőforrást.
CustomizeHttpModule osztálykönyvtár
A példa ASP.NET alkalmazásban létrehoztunk egy saját osztálykönyvtárat a modul számára. A modul forráskódját a HttpModuleTest ASP.NET alkalmazás mappájának CustomizeHttpModule alkönyvtárában találjuk meg, fordításkor a keletkező .DLL állomány a Web-alkalmazás /bin mappájába kerül, így az alkalmazást futtatva az rögtön megtalálja, metódusait eléri.
Az alkalmazásban egy hivatkozást kellett megadni az osztálykönyvtárra.
A modult tartalmazó C# kód az eventsModule osztályban található, melyben implementáltuk az IHttpModule interfész két metódusát. Az Init metódusban két eseményhez deklaráltunk egy-egy kezelőmetódust. A kezelőmetódusok a kérés beérkezésének (OnBeginRequest), valamint autentikációjának (OnAuthenticateRequest) eseményéhez kapcsolódnak:
public class eventsModule : IHttpModule
{
  public void Init(HttpApplication app)
  {
    app.BeginRequest += new EventHandler(OnBeginRequest);
    app.AuthenticateRequest += new EventHandler(OnAuthenticateRequest);
  }
  public void Dispose(){ }
Az eseményekhez létrehozunk egy delegált típust, majd ezt példányosítjuk:
  public delegate void MyEventHandler(Object s, EventArgs e);
  private MyEventHandler _eventHandler = null;
Gondoskodunk arról, hogy az események kezelhetők legyenek az alkalmazás Global.asax állományában és a modulban:
public event MyEventHandler MyEvent
{
  add { _eventHandler += value; }
  remove { _eventHandler -= value; }
}
Végül létrehozunk egy-egy metódust az események kezelésére egy-egy szöveg kiírását adva ezeknek feladatul:
public void OnBeginRequest(Object s, EventArgs e)
{
  HttpApplication app = s as HttpApplication;
  app.Context.Response.Write("<font size=4pt>A kérés a 'CustomizeHttpModule.eventsModule' adott eseménykezelőit indítja:<br></font>");
  app.Context.Response.Write("<font color=green>1. OnBeginRequest esemény<br></font>");
  if(_eventHandler!=null)
    _eventHandler(this, null);
}
public void OnAuthenticateRequest(Object s, EventArgs e)
{
  HttpApplication app = s as HttpApplication;
  app.Context.Response.Write("<font color=red>2. OnAuthenticateRequest esemény<br></font>");
  if(_eventHandler!=null)
    _eventHandler(this, null);
}
A modul kész, lefordítva a keletkező .DLL állomány bekerül a HttpModuleTest mappa /bin alkönyvtárába, futtatáskor az alkalmazás használja.
HttpModuleTest alkalmazás
Ahhoz, hogy alkalmazásunk használhassa fejlesztett modulunkat, szükséges néhány bejegyzést tenni a Web.config állományban. Itt a <httpModules> elem attribútumai segítségével meg kell adni, hogy alkalmazásunk hol keresse a modul osztályát. A <httpModules> tag szintaxisa a következő:
<httpModules>
   <add type="classname,assemblyname" name="modulename" />
   <remove name="modulename" />
   <clear />
</httpModules>
Az egyes attribútumok értelme a következő:
Albejegyzés Magyarázat Attribútum Magyarázat
add Hozzáad egy modult az alkalmazáshoz. name A modul neve.
- - type A tartalmazó osztály és assembly, egymástól veszővel elválasztva.
remove Töröl egy modult az alkalmazás modul-listájából. name A modul neve.
clear Megszüntet minden modul-szintű összerendelést. - -
A HttpModuleTest alkalmazás Web.config állományában a következő bejegyzéssel adtuk a modult az alkalmazáshoz:
<configuration>
   <system.web>
      <httpModules>
         <add name="CustomizeHttpModule" type="CustomizeHttpModule.eventsModule, CustomizeHttpModule" />
      </httpModules>
   </system.web>
</configuration>
Az assembly neve megegyezik általában a fordítás után keletkező .DLL állomány nevével.
Az alkalmazás Global.asax állományában is megvalósítottunk egy kezelő függvényt, mely minden modul-szintű esemény kezelésekor lefut. Feladata csak egy szöveget írni a HTML adatfolyamba tájékoztatást adva a kérés útvonalának adott állomásáról:
<%@ Import Namespace="CustomizeHttpModule" %>
<script language="C#" runat=server >
  protected void CustomizeHttpModule_OnMyEvent(Object src, EventArgs e)
  {  
    Context.Response.Write("<font color=lilac>A Global.asax OnMyModule eseménykezelője minden modul-eseményre lefut.<br></font>");
  }
</script>
Végül elhelyeztünk egy metódust a WebForm1.aspx lap kódjában is, mely kiírja, hogy éppen az oldal került sorra, mint a beérkező kérés utolsó állomása:
<%@ Page language="c#" Codebehind="WebForm1.aspx.cs" AutoEventWireup="false" Inherits="HttpModuleTest.WebForm1" %>
<%
  Response.Write("<font color=blue size=4pt>3. WebForm1.aspx oldal kódja fut.<br></font>");
%>
A kezelőmetódusok egyszerű funkciót valósítanak meg, de valóságos alkalmazásokban igen hasznos logika rendelhető az egyes szinteken keletkező eseményekhez.