Exception Filters

MVC امکانی با عنوان Exception Filters را فراهم کرده است که در این مقاله به آن میپردازیم. Exceptionها در عین حال که مفید هستند می توانند باعث دردسر نیز باشند.

Exception ها بخشی از اپلیکیشن هستند که در عین حال که مفید هستند، می توانند باعث دردسر و محدودیت نیز باشند.

در عین حال که به برنامه نویسان امکان بررسی خطاهای کوچک و بزرگ اپلیکیشن را می دهد، اما زمانی که کاربر را به جای صفحه موردنظر به صفحه زرد رنگ خطا هدایت می کند، ممکن است ناراحت کننده باشد.

بنابراین برای جلوگیری از این مسئله، برنامه نویسان این Exception ها را مدیریت می کنند.

اما با این حال باز هم Exception های مدیریت نشده ای باقی می ماند.

MVC امکانی با عنوان Exception Filters را فراهم کرده است که در این مقاله به آن می پردازیم.

زمانی که Exceptionای مدیریت نشده و توسط درخواستی از کاربر رخ بدهد، فیلترهای Exception اجرا می شوند. دلیل ایجاد exception می تواند هر چیزی باشد که این منبع وقوع exception است.

Exception Filters

Exception Filterهای سفارشی باید Interface موجود در MVC یعنی IExceptionFilter را پیاده سازی کنند.

این Interface به شکل زیر است:

public interface IExceptionFilter
{  
   void OnException(ExceptionContext filterContext)  
}

هر زمان که یک exception مدیریت نشده رخ دهد، متد OnException() فراخوانی می شود.

پارامتر ExceptionContext همانطور که مشاهده می کنید، از ControllerContext ارث بری می کند و تعدادی ویژگی (property) از پیش تعریف شده دارد که می تواند اطلاعاتی درباره درخواستی که باعث exception شده است، به ما بدهد.

Propertyهایی که ExceptionContext ارسال می کند به صورت زیر می باشند:

Result از نوع ActionResult:

نتیجه توسط رویدادی که درخواست شده، برگردانده می شود.

Exception از نوع Exception

Exceptionهای مدیریت نشده ای هستند که توسط رویدادها در اپلیکیشن ها رخ می دهند.

ExceptionHandled از نوع بولین

یک property بسیار ساده است که یک مقدار بولین برمی گرداند که اگر این exception توسط یکی از فیلترهای اپلیکیشن مدیریت شده باشد، این مقدار True و در غیر این صورت false می باشد.

Exception ای که رخ می دهد توسط property به نام Exception بررسی می شود و زمانی که مدیریت شد، به ExceptionHandled تحویل داده می شود بنابراین بقیه درخواست های فیلتر برای مدیریت exception لغو می شوند.

مشکل این جاست که اگر exceptionها مدیریت نشوند، MVC به طور پیش فرض صفحه زردرنگ خطا را نمایش می دهد.

این کار تاثیر زیادی روی کاربر می گذارد و مهم تر از آن اطلاعات امنیتی مربوط به اپلیکیشن را در دسترس دیگران می گذارد و ممکن است هکرها به این اطلاعات دست پیدا کنند.

بنابراین لازم است که exceptionها بسیار دقیق مدیریت شوند.

در زیر، یک مثال ساده از exception filter سفارشی شده را مشاهده می کنید که این فیلتر می تواند در فولدر Filters در Solution شما ذخیره شود.

ابتدا یک کلاس یا فایل به نام CustomExceptionFilter.cs ایجاد می کنیم.

public class CustomExceptionFilter: FilterAttribute,  
IExceptionFilter   
{  
    public void OnException(ExceptionContext filterContext)   
    {  
        if (!filterContext.ExceptionHandled && filterContext.Exception is NullReferenceException)   
        {  
            filterContext.Result = new RedirectResult("customErrorPage.html");  
            filterContext.ExceptionHandled = true;  
        }  
    }  
}  

حال ببینیم که این کلاس دقیقا چه کاری انجام می دهد.

همانطور که مشاهده می کنید، این کلاس interface ای را که قبل تر گفتیم پیاده سازی می کند و درواقع به این ترتیب متد ()onException را پیاده سازی می کند.

این متد پارامتری با عنوان ExceptionContext دارد که propertyهای آن در یک جدول مشخص می شوند.

در این فیلتر سفارشی، exception بسیار رایج “Null Reference Exception” که وقتی مقدار بازگشتی null مدیریت/بررسی نشده رخ می دهد و در پیاده سازی های بیشتر استفاده می شود.

این فیلتر سفارشی از FilterAttribute ارث بری می کند پس می تواند به عنوان یک Attribute و یا به طور مستقیم مانند یک کنترلر [CustomExceptionFilter] استفاده شود.

در پیاده سازی بالا، تقریبا تمام property های مهم ExceptionContext را استفاده کردیم.

ابتدا بررسی می شود که آیا این ExceptionContext از نوع ExceptionHandled هست یا خیر که یک مقدار بولین برمی گرداند که این exception مدیریت شده هست یا خیر، اگر مدیریت نشده باشد نوع exception رخ داده را بررسی می کند.

تا اینجا NullReferenceException را بررسی کردیم حال result را تغییر داده و RedirectResult را برمی گردانیم (که از نوع ActionResult است) و به کاربر این امکان را می دهیم که به جای صفحه زردرنگ خطا، صفحه سفارشی خطا را که در اپلیکیشن طراحی شده است، مشاهده نماید.

استفاده از فیلتر بسیار ساده است چرا که این فیلتر از FilterAttribute ارث بری می کند، بنابراین بسته به کاربرد آن می تواند به عنوان [CustomExceptionFilter] در سطح کنترلر یا به صورت یک Action استفاده شود که هیچ تفاوتی با هم ندارند.

//Over controller  
[CustomExceptionFilter]  
public class HomeController:Controller 
{  
   //......  
}    
//Over the Action  
[CustomExceptionFilter]  
public ActionResult Index() 
{  
   //.......  
} 

حال به HandleAttribute که به صورت پیش فرض در MVC وجود دارد، می پردازیم.

یک کلاس پیش فرض است که مانند صفت فیلتر (filter attribute) در MVC استفاده می شود.

نکته مهم این است که این attribute تنها وقتی کار می کند که custom errors در web.config فعال باشد.

حالت پیش فرض این المنت RemoteOnly است که فقط زمانی کار می کند که اپلیکیشن روی هاست قرار گرفته باشد و درخواست از سیستم های دیگر ارسال شده باشد. در ادامه به property های HandleAttribute می پردازیم:

ExceptionType: این property همانطور که از نام آن مشخص است، نوع exceptionای را که باید مدیریت شود مشخص می کند.

View: این property مشخص می کند که پس از مدیریت exception کاربر به چه صفحه ای هدایت شود.

Master: اگر لایه ای (layout) برای صفحه خطا داشته باشیم، می توانیم مسیر آن را به عنوان Master مشخص نماییم. اگر هیچ مقداری به آن ندهیم، از لایه پیش فرض برای صفحه خطا استفاده خواهد کرد.

کد زیر نحوه استفاده از HandleError را نشان می دهد:

[HandleError(ExceptionType = typeof(NullReferenceException), View = "CustomErrorPage)] 
{  
   public Action Result 
   {  
      //........  
      var testVal = null;  
      //Unhandled and used..  
   } 
} 

توجه داشته باشید که وقتی از HandleError Attribute استفاده می کنیم، در صفحه سفارشی خطا باید از اطلاعات HandleError مانند Stack Trace، پیغام exception مناسب و… استفاده نماییم.

از آنجا که ما نمی خواهیم این اطلاعات را به کاربر نشان دهیم، باید stack Trace را در یک فیلد مخفی قرار دهیم یا تگ HTML آن را invisible کنیم زیرا view به کاربر نمایش داده نمی شود مگر اینکه Exception.StackTrace در View آمده باشد.

به این ترتیب ایجاد فیلترهای Exception را با هم بررسی کردیم. روش ها و ابزارهای زیادی برای مدیریت exception ها وجود دارد، اما هنوز می توان با استفاده از این فیلترها از تاثیرات خطاهای ناگهانی روی اپلیکیشن جلوگیری کرد.

موفق باشید !

داریوش فرخی

داریوش فرخی هستم از سال 92 شروع به یادگیری برنامه نویسی و از سال 93 در بخش برنامه نویسی و تولید محتوای سایت mspsoft.com مشغول هستم. فعالیتم نیز بیشتر در زمینه های برنامه نویسی با سی شارپ و asp.net بوده است. اوقات فراغتم را هم غالبا با تماشای فیلم یا بازی های کامپیوتری پر میکنم .

نوشته‌های مرتبط

دیدگاه‌ها

*
*

این سایت از اکیسمت برای کاهش هرزنامه استفاده می کند. بیاموزید که چگونه اطلاعات دیدگاه های شما پردازش می‌شوند.