فیلترها در MVC
نویسنده: امیر هاشم زاده
تاریخ: ۱۳۹۴/۱۱/۲۷ ۱:۵
آدرس: www.dntips.ir
| مطالب | ۳۶۹۴ |
| نویسندگان | ۲۷۶ |
| گروههای مطالب | ۱۰۲۴ |
| نقشههای راه | ۱۱۹ |
| دورهها | ۱۴ |
| اشتراکها | ۱۷۹۱۴ |
| نوع | توضیح | فیلتر توکار | اینترفیس |
| Authorization | انجام عملیات احراز هویت و سطح دسترسی، قبل از اجرای کد اکشن متد | [Authorize] و [RequireHttps] | IAuthorizationFilter |
| Action | اجرای کدهایی قبل از اجرای کدهای اکشن متد | IActionFilter | |
| Result | اجرای کدهایی قبل یا بعد از تولید ویو (View result) | [OutputCache] | IResultFilter |
| Exception | اجرای کدهایی در صورت وجود استثنای مدیریت نشده | [HandleError] | IExceptionFilter |
[HandleError]
public class HomeController : Controller
{
public ActionResult Index()
{
//throw exception for demo
throw new Exception("This is unhandled exception");
return View();
}
public ActionResult About()
{
return View();
}
public ActionResult Contact()
{
return View();
}
} <customErrors mode="On" />
بصورت پیش فرض MVC از سه طریق زیر فیلترها را جهت استفادهی در برنامه فراهم میکند:
در ادامه با نحوهی ایجاد یک فیلتر، بوسیلهی هر یک از روشهای بالا، با ذکر مثالی بیشتر آشنا خواهید شد.
همانطور که در ابتدا اشاره شد، در MVC چهار نوع فیلتر معرفی شده است که امکان استفادهی از آنها بهصورت همزمان در سطح کنترلر و یا اکشن متد وجود دارد. اما ترتیب اجرای آنها متفاوت و به ترتیب زیر است:
فیلترها براساس ترتیب اشاره شدهی در بالا اجرا خواهند شد. در صورتیکه چند فیلتر از یک نوع استفاده شود، جهت تقدم و تاخر در اجرا، از خاصیت Order استفاده خواهد شد. بعنوان مثال در کد زیر بدلیل خاصیت Order=1 ابتدا AuthorizationFilterB و سپس AuthorizationFilterA اجرا میشود.
[AuthorizationFilterA(Order=2)]
[AuthorizationFilterB(Order=1)]
public ActionResult Index()
{
return View();
} public enum FilterScope
{
First = 0,
Global = 10,
Controller = 20,
Action = 30,
Last = 100,
} نکته: مقدار Scope فیلترهای Authorization برابر 0 و فیلترهای Exception برابر 100 میباشد.
روش اول: پیاده سازی اینترفیس یکی از انواع فیلترها و ارث بری از کلاس FilterAttribute
در این روش متدهایی که باید پیاده سازی شوند متفاوت خواهد بود. به همین جهت متدهای هر نوع بشرح زیر معرفی میشود:
// Called when authorization is required void OnAuthorization(AuthorizationContext filterContext)
// Called after the action method executes void OnActionExecuted(ActionExecutedContext filterContext) // Called before an action method executes void OnActionExecuting(ActionExecutingContext filterContext)
// Called after an action result executes void OnResultExecuted(ResultExecutedContext filterContext) // Called before an action result executes void OnResultExecuting(ResultExecutedContext filterContext)
// Called when an exception occurs void OnException(ExceptionContext filterContext)
یادآوری: همانطور که در ابتدای مقاله اشاره شد، فیلترها قبل یا بعد از اجرای اکشن متدها فراخوانی خواهند شد. بنابراین به کامنت بالای متد فیلترها دقت داشته باشید.
مثال: پیاده سازی اینترفیس IExceptionFilter و ارث بری از کلاس FilterAttribute جهت تهیهی فیلتری سفارشی از نوع Exception
class CustomErrorHandler : FilterAttribute, IExceptionFilter
{
public override void IExceptionFilter.OnException(ExceptionContext filterContext)
{
Log(filterContext.Exception);
base.OnException(filterContext);
}
private void Log(Exception exception)
{
//log exception here..
}
} // Called by MVC after the action method executes void OnActionExecuted(ActionExecutedContext filterContext) // Called by MVC before the action method executes void OnActionExecuted(ActionExecutedContext filterContext) // Called by MVC after the action result executes void OnResultExecuted(ResultExecutedContext filterContext) // Called by MVC before the action result executes void OnResultExecuting(ResultExecutingContext filterContext)
public class LogAttribute : ActionFilterAttribute
{
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
Log("OnActionExecuted", filterContext.RouteData);
}
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
Log("OnActionExecuting", filterContext.RouteData);
}
public override void OnResultExecuted(ResultExecutedContext filterContext)
{
Log("OnResultExecuted", filterContext.RouteData);
}
public override void OnResultExecuting(ResultExecutingContext filterContext)
{
Log("OnResultExecuting ", filterContext.RouteData);
}
private void Log(string methodName, RouteData routeData)
{
var controllerName = routeData.Values["controller"];
var actionName = routeData.Values["action"];
var message = String.Format("{0}- controller:{1} action:{2}", methodName,
controllerName,
actionName);
Debug.WriteLine(message);
}
}
روش چهارم: ارث بری از کلاس فیلترهای توکار و مهیای در MVC و تحریف متدهای آن
در کد زیر با تحریف و سفارشی سازی متد OnException مخصوص فیلتر توکار HandleError، قابلیتهای آن افزایش یافته است:
class CustomErrorHandler : HandleErrorAttribute
{
public override void OnException(ExceptionContext filterContext)
{
Log(filterContext.Exception);
base.OnException(filterContext);
}
private void Log(Exception exception)
{
//log exception here..
}
} درصورتی که قصد داشته باشید فیلتری بصورت سراسری و در کل برنامه فعال گردد باید آن را در رویداد Application_Start فایل Global.asax.cs بوسیلهی متد RegisterGlobalFilters کلاس FiterConfig رجیستر نمایید. بعد از آن فیلتر به کلیهی کنترلرها و اکشن متدها اعمال میگردد.
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
}
}
// FilterConfig.cs located in App_Start folder
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
// add your new custom filters
filters.Add(new LogAttribute());
filters.Add(new CustomErrorHandler());
}
} در کد بالا فیلتر توکار HandleError و البته فیلترهای سفارشی دیگری نیز به صورت سراسری به تمام اکشن متدهای کنترلرها اعمال گردیده است.
[HandleError] public class HomeController : Controller
public class HomeController : Controller
{
[HandleError]
public ActionResult Index()
{
return View();
}
}