نحوه نوشتن HttpModule

یک HttpModule کلاسی است که از IHttpModule ارثبری میکنید و دو متد Init و Dispose را پیاده سازی میکند. همانطور که از اسم این دو متد مشخص است، در متد Init کارهای اولیه و آماده سازی HttpModule انجام میشود و در متد Disposeهرگونه آزاد سازی منابع که مورد نیاز است انجام میشود.
بسیاری از اوقات در متد Dispose کد خاصی نوشته نمیشود اما در متد Init باید رویدادهایی که میخواهیم از آنها استفاده کنیم را مشخص کنیم. پارامتر ورودی متد Init یک شئ از نوع HttpApplication است که اطلاعات Application جاری را در خود دارد و اتصال رویدادها از طریق آن انجام میشود. به عنوان مثال به کد نمونه زیر توجه کنید:

class SampleHttpModule : IHttpModule

{

public void Dispose(){}

public void Init(HttpApplication context)

{

context.BeginRequest += new EventHandler(context_BeginRequest);

context.EndRequest += new EventHandler(context_EndRequest);

}

void context_BeginRequest(object sender, EventArgs e)

{

//handle BeginRequest here…

}

void context_EndRequest(object sender, EventArgs e)

{

//handle EndRequest here…

}

}

همانطور که در کد بالا مشاهده میشود، هر کدام از رویدادهای BeginRequest و EndRequest دارای دو پارامتر ورودی هستند که پارامتر اول (در اینجا sender) همان شئ HttpApplication است که برای دسترسی به اطلاعات درخواست، تغییر پاسخ سرور، دسترسی به Cache، دسترسی به Session و … از این شئ استفاده میکنیم.
به عنوان مثال فرض کنیم که میخواهیم در انتهای هرکدام از صفحات سایت یک پیغام اضافه کنیم. همانطور که حدس میزنید، برای این کار از رویداد EndRequest میتوانیم استفاده کنیم. البته دقت کنید که یک HttpModule برای تمام درخواستها فراخوانی خواهد شد، پس در کد مورد نظر، باید حتما بررسی کنیم که در صورتی که درخواست صورت گرفته برای یک صفحه (Page) بوده این متن را به انتهای درخواست اضافه کنیم. بنابراین برای این مثال به شئ Response (برای نوشتن اطلاعات در آن) و شئ Context (برای بررسی Handler آن که نشاندهنده Handler استفاده شده برای درخواست جاری است) نیاز داریم.
نکته: در صورتی که با بحث HttpHandler آشنایی ندارید، پیشنهاد میکنم در این مورد نیز مطالعه کنید ولی برای الان فقط این را بدانید که اگر درخواست یک صفحه عادی دریافت شده باشد، Handler از نوع System.Web.UI.Page خواهد بود.
بنابراین کد کامل مورد نظر برای این ماژول به صورت زیر خواهد بود:

namespace MyApplication

{

class SampleHttpModule : IHttpModule

{

public void Dispose() { }

public void Init(HttpApplication context)

{

context.EndRequest += new EventHandler(context_EndRequest);

}

void context_EndRequest(object sender, EventArgs e)

{

HttpApplication application = (HttpApplication)sender;

if (application.Context.Handler is System.Web.UI.Page)

{

application.Response.Write(“<hr>This works!”);

}

}

}

}

شیوه استفاده از یک HttpModule:

تا اینجا نحوه نوشتن یک HttpModule را دیدیم. بعد از نوشتن یک HttpModule برای استفاده از آن باید این HttpModule را در فایل web.config معرفی کنیم تا از این به بعد سرور در هنگام اجرای رویدادهای مورد نظر، HttpModule ما را نیز دخالت دهد! تنظیمات مورد نیاز برای این کار بسته به نسخه IIS که استفاده میکنیم متفاوت است.
در IIS 6 و قبل از آن، (ویندوز ۲۰۰۳ و قبل از آن) برای استفاده از یک HttpModule آن را در بخش httpModules (در قسمتsystem.web) قرار میدهیم و در IIS 7 به بعد (ویندوز ۲۰۰۸ به بعد) برای این کار از بخش modules (در قسمتsystem.webServer) استفاده میکنیم. به عنوان مثال برای اضافه کردن ماژول مثال بالا در IIS 6 تنظیمات فایل web.config را به این صورت انجام میدهیم:

<configuration>

<system.web>

<httpModules>

<add name=”SampleHttpModule” type=”MyApplication.SampleHttpModule”/>

</httpModules>

</system.web>

</configuration>

برای IIS 7 تنظیمات به این صورت انجام میشود:

<configuration>

<system.webServer>

<modules>

<add name=”SampleHttpModule” type=”MyApplication.SampleHttpModule”/>

</modules>

</system.webServer>

</configuration>

نکته: اگر هر دو قسمت ذکر شده را در فایل web.config اضافه کنیم (به عنوان مثال در حالتی که بخواهیم یک فایلweb.config در هر دو حالت IIS 6 و IIS 7 کار کند) در IIS 7 با خطا روبرو میشویم که برای رفع این خطا میتوانیم از تگvalidation (در قسمت system.webServer) با ویژگی validateIntegratedModeConfiguration=false استفاده کنیم. به عنوان مثال فایل web.config مورد نیاز برای مثال قبلی در این حالت به این صورت خواهد شد:

<configuration>

<system.web>

<httpModules>

<add name=”SampleHttpModule” type=”MyApplication.SampleHttpModule”/>

</httpModules>

</system.web>

<system.webServer>

<validation validateIntegratedModeConfiguration=”false” />

<modules>

<add name=”SampleHttpModule” type=”MyApplication.SampleHttpModule”/>

</modules>

</system.webServer>

</configuration>