PDA

View Full Version : یک توضیح کلی در ارتباط با HttpModule ها و HttpHandler ها ؟



torisoft
دوشنبه 13 فروردین 1386, 19:05 عصر
سلام بر دوستان عزیز سال نو مبارک.
لطفا یکی در ارتباط با HttpModule ها و HttpHandler ها یک توضیح کامل بده و چندتا مثال کاربردی هم بگه ممنون می شم.

manager
دوشنبه 13 فروردین 1386, 21:36 عصر
با استفاده از HttpModule و HttpHandler شما می توانید عملیات سطح پائین تری را با درخواست ها و پاسخ های Client انجام دهید. در حقیقت HttpModule و HttpHandler دو ابزار برای Componentizing کردن Web App هستند. وظیفه ی یک HttpHandler رندر کردن منبع خاص و یا نوع خاصی از یک منبع خاص می باشد. در حقیقت هر وقت که شما یک صفحه ی aspx را به پروژه خود اضافه می کنید در واقع یک HttpHandler ایجاد کرده اید. به این خاطر که هنگامی که بخشی از HTML صفحه ی aspx شما در هنگام زمان اجرا کامپایل می شود و به صورت مستقیم یا غیر مستقیم از System.Web.UI.Page به ارث می برد که این باعث پیاده سازی یک HttpHandler می شود. در حقیقت کلاس System.Web.UI.Page یک HttpHandler هستش که باعث رندر شدن صفحه ی aspx می شود. البته احتمالا شما از این موضوع تا به حال کاملا بی اطلاع بودید و نیازی هم نیست که بدانید در پشت صحنه چه می گذرد.
بعضی وقت ها شما نیاز دارید که در ازای شروع هر درخواست یک کد خاص اجرا شود . مثلا فرض کنید شما نیاز دارید که بدانید کاربر به چه صفحه هایی در وب سایتتان می رود. یک راه اینکه کد Logging که این عمل را برایتان انجام می دهد را در Pgae_Load هر صفحه بگذارید که آشکارا دارای هزینه ی بالائی برای Maintenance و Reusability هست. مثلا باید برای تمام صفحات این کار را انجام دهیم و یا تصور کنید سایتتان 300 صفحه دارد، حال می خواهید در کنار Logging یک عمل دیگرنیز انجام دهید، حتی تصورش هم عذاب آور است. اما راه خوب و آسان این کار که امتیاز خوبی نیز در Maintenance و Reusability دارد، استفاده از HttpModule هاست. شما یک Dll ایجاد می کنید که از IHttpModule پیروی کند و بعد تمام. اگر خواستید به راحتی می تونید از این Module در سایر وب سایت ها نیز استفاده کنید با کمترین هزینه تغییرات.


http://mfarahy.persiangig.com/image/121.jpg

HttpHandler ها امکاناتی دارند که می توانید با استفاده از آنها منابع و یا مسیرهای خاصی را به آنها نسبت دهید و هنگام درخواست آن منابع یا مسیرها از سمت Client، موتور asp.net این درخواست را به HttpHandler شما تسلیم می کند و حالا HttpHandler شما وظیفه ی Render کردن آن درخواست را بر عهده دارد. مثلا در مثال زیر شما تعیین می کنید که در صورتی که کاربر صفحاتی با پسوند ashx را درخواست کرده بود، آنگاه کنترل درخواست به HttpHandler ای که شما مشخص کرده اید هدایت شود.( این کد را باید در web.config در میان تگ های <system.web> و </system.web> قرار دهید.)


<httpHandlers>
<add path="*.ashx" verb="*" type="Farahy.MyHttpHandler, MyHttpHandler"/>
</httpHandlers>
هر HttpHandler باید اینترفیس IHttpHandler را پیاده سازی کند. این اینترفیس دو عضو دارد. یکی خصوصیت IsReusable است که مشخص می کند آیا یک درخواست دیگر می تواند از نمونه ی آن استفاده کند یا خیر. عضو دیگر IHttpHandler متد ProcessRequest است که وظیفه ی پردازش یک Request را بر عهده دارد.


public bool IsReusable
{
get
{
return true;
}
}

public void ProcessRequest(HttpContext context)
{
context.Response.Write("<BR/>HttpHandler :::: ProcessRequest<BR/>");
}
اما elementهای مهم تگ add میان <httpHandlers> و </httpHandlers> عبارت است از :
path : مشخص می کند این HttpHandler باید نسبت به چه مسیری و یا چه نوع منابعی گوش به زنگ باشد. به عنوان مثال path=” *.simg”
verb : مشخص می کند این HttpHandler نسبت به چه نوع Request باید فعال شود. مقادیر مجاز برای این element عبارت است از GET, POST, HEAD.

با استفاده از تنظیمات زیر در فایل web.config شما می توانید نسبت به معرفی و ثبت یک HttpModule اقدام کنید.

<add name="ModuleName"
type=".NET Class, Assembly [,Version=version number]
[,Culture=culture] [,PublicKeyToken=token]"/>هر کلاس HttpModule باید اینترفیس IHttpModule را پیاده سازی کند. این اینترفیس دو عضو دارد. یکی متد مهم Init است که در آن شما به شیئ HttpApplication دسترسی دارید و با استفاده از آن می تونید وقایعی را که نیاز به Handle کردن دارند را مشخص کنید. مثلا در کد زیر من دو واقعه ی BeginRequest و EndRequest را Handle می کنم.


public void Init(HttpApplication context)
{
HttpContext.Current.Response.Write("<BR/>HttpModule :::: Init<BR/>");
context.BeginRequest += new EventHandler(context_BeginRequest);
context.EndRequest += new EventHandler(context_EndRequest);
}
void context_EndRequest(object sender, EventArgs e)
{
HttpApplication app = (HttpApplication)sender;
app.Response.Write("<BR/>HttpModule :::: context_EndRequest<BR/>");
}

void context_BeginRequest(object sender, EventArgs e)
{
HttpContext.Current.Response.Write("<BR/>HttpModule :::: context_BeginRequest<BR/>");
}
شیئ sender در هر Event همان شیئ HttpApplication است.

با استفاده از مثال حاظر می توانید مراحل مراحل اجرای یک HttpModule و HttpHandler را مشاهده کنید.


http://mfarahy.persiangig.com/image/122.jpg

دانلود (http://mfarahy.persiangig.com/Training/examples/HttpHandlersModules.rar)


(http://mfarahy.persiangig.com/Articles/HttpHandlers_HttpModules.pdf)

amir.NET2
سه شنبه 14 فروردین 1386, 15:46 عصر
ممنون از مقالتون

اگه میشه خصوصیت IsReusable رو بیشتر توضیح بدید

با تشکر

manager
سه شنبه 14 فروردین 1386, 23:26 عصر
هنگامی که یک درخواست از طریق Client به سرور ارسال می شود، موتور Asp.net به ازای پردازش هر درخواست یک Thread ایجاد می کند. IHttpHandler.IsReusable مشخص می کند که آیا یک نمونه از کلاس HttpHandler شما می تواند برای پردازش چندین درخواست همزمان مورد استفاده قرار گیرد یا خیر. در صورتی که HttpHandler شما مقدار true را برای این خصوصیت باز گرداند، کد موجود در متد ProcessRequest باید ThreadSafe بوده و مراقب باشید که هیچ گونه حالتی را نمی توانید در این مد در اختیار داشته باشید. همچنین در این حالت باید مراقب منابع مشترک که مورد استفاده ی درخواست های همزمان دیگر می باشد باشید. این حالت نسبت به حالتی دیگر (حالتی که IHttpHandler.IsReusable شما مقدار false را بر می گرداند) دارد و آن هزینه کمتر استفاده از منابع سیستمی می باشد. مثلا در مثال تولید تصاویر امنیتی با استفاده از HttpHandler چون از منابع مشترک استفاده نمی کند و به حالت وابسته نیست می توان برای پائین آوردن هزینه اشغالی منابع در وضعیتی که چندین Request به صورت Concurrent پردازش می شود، از حالت Reusable استفاده نمود.
البته کارائی این خصوصیت در سایت های بزرگ که یکباره با طیف وسیعی از درخواست ها مواجه می شوند، محسوس است.
پیشنهاد می کنم اگر تمایل به ایجاد یک HttpHandler داشتید مقدار بازگشتی IsReusable را با دقت انتخاب کنید.