MVC Filter

Filters inject extra logic into the request processing pipeline.

They provide a simple and elegant way to implement cross-cutting concerns.

英文资料的开篇给出了Filter的定义:1.在请求过程中注入额外的逻辑 2.用优雅的方式分离关注点


根据时间点分类:

Authorization --> Action --> Result , Exception

IAuthorizationFilter:在所有的Filter中最早执行的,可用于Action的权限控制

IActionFilter:在Action执行的前后,可用于请求跳转、记录Action执行日志

IResultFilter:在Result执行的前后,可用于记录Result执行日志

IExceptionFilter:在任何异常发生时,可用于记录日志、处理异常、指定错误页面


如何使用:

// 1.在Global.asax中定义,应用在所有的Action上
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
    filters.Add(new HandleErrorAttribute());
}
// 2.在Controller上定义,应用在包含的Action上
[CustomAuthorize]
public class BaseController : Controller
{}
// 3.在Action上定义,应用在该Action上
[ValidateAntiForgeryToken]
[HttpPost]
public virtual ActionResult PostAction(string input)
{
    string output = "You have input: " + input;
    return RedirectToAction(MVC.AvoidDuplicateSubmit.GetAction(output));
}

同一类型的Filter执行时有先后顺序:Global > Controller > Action ,

只有IExceptionFilter的顺序是倒过来的



自定义Filter:

// 1.自定义授权Filter
public class CustomAuthorizeAttribute : AuthorizeAttribute
{
    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        // 不对ChildAction进行权限检查
        if (filterContext.IsChildAction)
        {
            return;
        }

        base.OnAuthorization(filterContext);
    }

    /// <summary>
    /// 授权逻辑
    /// </summary>
    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        string controllerName = httpContext.Request.RequestContext.RouteData.Values["controller"].ToString();
        string actionName = httpContext.Request.RequestContext.RouteData.Values["action"].ToString();
        string action = string.Format("/{0}/{1}", controllerName, actionName);

        // 允许的Role:action --> Activity --> Roles
        base.Roles = SysContext.GetRolesForActivity(action);

        // 用户的Role:从Session或Cookie中取得(在哪存的到哪取)
        string userRole = "Guest";
        httpContext.User = new GenericPrincipal(httpContext.User.Identity, new string[] { userRole });

        return base.AuthorizeCore(httpContext);
    }

    /// <summary>
    /// 无权限处理
    /// </summary>
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        if (filterContext.HttpContext.Request.IsAjaxRequest())
        {
            // Ajax须返回JsonResult
            filterContext.Result = new JsonResult
            {
                Data = new { Error = "未授权", LogOnUrl = FormsAuthentication.LoginUrl },
                JsonRequestBehavior = JsonRequestBehavior.AllowGet
            };
        }
        else
        {
            // 默认显示登录页面,也可以自定义
            filterContext.Result = new ViewResult { ViewName = MVC.Shared.Views.Error };
            // base.HandleUnauthorizedRequest(filterContext);
        }
    }
}

// 2.自定义ActionFilter
public class CustomActionAttribute : FilterAttribute, IActionFilter
{
    private Stopwatch timer;

    public void OnActionExecuting(ActionExecutingContext filterContext)
    {
        timer = Stopwatch.StartNew();
    }

    public void OnActionExecuted(ActionExecutedContext filterContext)
    {
        timer.Stop();

        string action = string.Format("/{0}/{1}",
            filterContext.ActionDescriptor.ControllerDescriptor.ControllerName,
            filterContext.ActionDescriptor.ActionName);
        string exacuteTimeLog = string.Format("\r\nAction: {0}   ElapsedTime: {1}ms \r\n", action, timer.Elapsed.TotalMilliseconds);

        SysContext.ActionPerformanceLogger.Debug(exacuteTimeLog);
    }
}
// 3.自定义ResultFilter
public class CustomResultAttribute : FilterAttribute, IResultFilter
{
    private Stopwatch timer;

    public void OnResultExecuting(ResultExecutingContext filterContext)
    {
        timer = Stopwatch.StartNew();
    }

    public void OnResultExecuted(ResultExecutedContext filterContext)
    {
        timer.Stop();

        string view = (((System.Web.Mvc.ViewResultBase)(filterContext.Result))).ViewName;
        string exacuteTimeLog = string.Format("\r\nView: {0}   ElapsedTime: {1}ms \r\n", view, timer.Elapsed.TotalMilliseconds);

        SysContext.ActionPerformanceLogger.Debug(exacuteTimeLog);
    }
}

// 4.自定义异常处理Filter
public class CustomExceptionAttribute : FilterAttribute, IExceptionFilter
{
    public void OnException(ExceptionContext filterContext)
    {
        Exception ex = filterContext.Exception;
            
        // 1.记录异常日志
        // TODO

        // 2.实施补救措施
        // TODO

        // 3.展示错误页面:默认为~/Views/Shared/Error.cshtml,由HandleErrorAttribute捕获
        if (ex is NullReferenceException)
        {
            filterContext.Result = new ViewResult { ViewName = MVC.Home.Views.Index };
        }
        else if (ex is HttpAntiForgeryException)
        {
            filterContext.Result = new RedirectResult("/Authentication/LogOn");
        }
        // ...
    }
}

MVC3内置的Filter:

IAuthorizationFilter:RequireHttps,ChildActionOnly,ValidationAntiForgeryToken,ValidateInput

IActionFilter:OutputCache,AsyncTimeout,NoAsyncTimeout

IExceptionFilter: HandleError

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值