专栏首页漫漫全栈路ASP.NET MVC 过滤器

ASP.NET MVC 过滤器

过滤器是 ASP.NET MVC 中很重要的一个功能,过滤器(Filters)的出现使得我们可以在ASP.NET MVC程序里更好的控制浏览器请求过来的URL,不是每个请求都会响应内容,只响应特定内容给那些有特定权限的用户。

简述过滤器

过滤器理论上有以下功能:

  • 判断登录与否或用户权限
  • 决策输出缓存
  • 防盗链
  • 防蜘蛛
  • 本地化与国际化设置
  • 实现动态Action(做权限管理系统的好东西)

实现过滤器的两种方法:

  • 自定义类继承自相应的类或借口,重写方法,作为特性使用
  • 在控制器类中重写方法 特性方法的使用:
    • 作为Controller或Action的特性
    • 在Global中注册为全局过滤器,应用于所有的Controller的Action

    注意:如果继承自接口,则需要让类实现FilterAttribute,才能作为特性使用。参数类均继承自ControllerContext,主要包含属性请求上下文,路由数据,结果。

过滤器的四种实现

四种常用的过滤器: 过滤器类型 | 接口 | 默认实现 | 描述 :–:|:–:|:–:|:–: Authorization | IAuthorization | AuthorizeAttribute | 首先运行,在其他过滤器的操作方法 Action | IActionFilter | ActionFilterAttribute | 运行之前和之后的动作方法 Result | IResultFilter | ActionFilterAttribute | 运行前后执行的操作结果 Exception | IExceptionFilter | HandleErrorAttribute | 如果只运行一个过滤器,操作方法或行动结果抛出一个异常

MVC5 中新增了 Authentication 过滤器,用于验证。在 MVC5 中,将原本的 Authorization 拆分为 Authentication(身份验证)和 Authorization(授权)两个,MVC 接受到 Web 页面请求时,首先将执行所有的 Authentication 过滤器,如果请求需要认证且已经被验证过了,就会继续下一步处理,若没有通过身份验证,则会停止处理。

下面先说下身份过滤验证器,然后以身份过滤验证器为例介绍几种实现过滤器的方法,再介绍后续的其他的过滤器!

身份验证过滤器

定义身份验证的过滤器,需要在约束的Action执行前来执行,重写OnAuthorization方法。

通过一个简单的实例,来展示Filter的模式:

创建过滤器

现在项目中添加一个 Filter 文件夹来存储过滤器,然后来写第一个 Filter 示例 - MyAuthorization.cs

using System.Web.Mvc;

namespace STU_mvc.Areas.UserManage.Filters
{
    public class MyAuthorization: AuthorizeAttribute
    {
        public override void OnAuthorization(AuthorizationContext filterContext)
        {
            //.net framework 默认身份验证
            //base.OnAuthorization(filterContext); 

            //跳转页面,使用Result,而不是使用Response.Redirect() 因为它会继续执行Action
            //filterContext.Result = new RedirectResult(UrlHelper.GenerateUrl("","","","","","",true));

            //获取路由数据,当前上下文匹配到路由规则后,得到的一个对象
            //filterContext.RouteData 

            //获取上下文
            filterContext.HttpContext.Response.Write("Test");
        }
    }
}

注意: 这是一个身份验证的 Filter ,因此这个类必须继承自System.Web.Mvc 中的 AuthorizeAttribute ,并对OnAuthorization()方法进行重写。

特性模式调用控制器

写好了 Filter 还得去调用他,调用 Filter 的方法就是,在 Action 前为其申明一个特性

using STU_mvc.Areas.UserManage.Filters;
using System.Web.Mvc;
namespace STU_mvc.Areas.UserManage.Controllers
{
    public class HomeController : Controller
    {
        // GET: UserManage/Home
        [MyAuthorization]
        public ActionResult Index()
        {
            return View();
        }
    }
}

如上代码中的控制器直接返回了一个 Test ,编译-运行-访问当前路由,会发现浏览器在 html 代码前直接附加了一个 Test ,由此可知,过滤器发生在 Action 之前。

注意:Filter 是作为特性而附加给 Action 的,因此可以被不同的 Action 重复调用,且只在调用后才会执行。同样,如果一个 Controller 中的所有 Action 都需要使用这个 Filter ,则可以直接给当前 Controller 类附加上这个 Filter 特性即可。

其他的过滤器调用方法

全局过滤器

Global.asxs 中 FilterConfig 调用了 App_Start 中的 FilterConfig.cs 文件,这个文件在全局中申明了过滤器,及所有在此处注册的过滤器,会被所有 Controller 的 所有 Action 执行。

public class FilterConfig
    {
        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            //filters.Add(new HandleErrorAttribute());

            //在全局中注册过滤器,则所有控制器的所有行为都会执行
            filters.Add(new MyAuthorization());
        }
    }

RegisterGlobalFilters() 方法的形参表面,filters 是一个集合,因此只需要在其中使用 filters 的 Add 方法申明过滤器即可。

重写方法实现过滤

针对某一控制器进行重写,应用范围为当前控制器下的所有的行为。

在控制器中 输入 override OnAuthentication 自动补全,为当前控制器重写该方法:

protected override void OnAuthentication(AuthenticationContext filterContext)
{
    filterContext.HttpContext.Response.Write("test for controller");
}

重写完成后,调试可以发现, 被重写OnAuthenticationhome 控制器执行了 filter 的内容,而未被重写的test 控制器则不受影响。

同样的,也可以添加一个继承自Controller 的基类,并重写基类的OnAuthentication ,之后让控制器不再继承Controller,而是间接继承基类。 即: HomeController -> BaseController -> Controller ,通过为 BaseController 重写 filter 来实现过滤器。

异常处理过滤器

异常处理过滤器,用于当发生异常时,进行自定义异步处理,记录日志,跳转页面等。

创建过滤器

首先创建过滤器 MyException.cs,同样的,在 Filter 文件夹下新建一个类,继承自 HandleErrorAttribute

注意:OnException 的 base 特性不能删除,否则捕获不到异常

namespace STU_mvc.Areas.UserManage.Filters
{
    public class MyExcepition: HandleErrorAttribute
    {
        public override void OnException(ExceptionContext filterContext)
        {
            //OnException 的 base 特性不能删除,否则捕获不到异常
            base.OnException(filterContext);

            //记录日志

            //直接跳转到异常处理页面
            filterContext.Result= new RedirectResult("/Error/400.html");
        }
    }
}

全局注册异常过滤器

然后使用全局注册,通常来说,异常处理都是全局有效的:

注意:如果要实现自定义

public class FilterConfig
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        //系统默认的异常处理过滤器
        //filters.Add(new HandleErrorAttribute());

        //在全局中注册过滤器,则所有控制器的所有行为都会执行
        //filters.Add(new MyAuthorization());

        //添加自己的异常处理过滤器
        filters.Add(new MyExcepition());
    }
}

配置启动自定义异常处理

注意: 要使用自定义的异常处理,需要在 web.config中为 system.web添加<customErrors mode ="on" /> 节点,开启自定义异常。

<system.web>
    <customErrors mode ="On" defaultRedirect="Error/400.html"/>
    ……

配置完成后,我们随便输入一个不匹配的路由,就会返回到我们提前编写好的400页面,并通过 url 暴露出异常的路由信息,而正常的路由请求则不受此影响。

##行为过滤器

Action 过滤器继承ActionFilterAttribute实现,并提供了在两个不同时间点执行代码的能力,分别在 行为执行前(OnActionExecuting)/行为执行后(OnActionExecuted) 执行相关操作。

创建过滤器

Filter 目录下新建一个类MyAction,并继承ActionFilterAttribute

public class MyAction: ActionFilterAttribute
{
	//行为执行前
	public override void OnActionExecuting(ActionExecutingContext filterContext)
	{
		filterContext.HttpContext.Response.Write("This line is Before Action execute!");
		//base.OnActionExecuting(filterContext);
	}

	//行为执行后,结果输出前
	public override void OnActionExecuted(ActionExecutedContext filterContext)
	{
		filterContext.HttpContext.Response.Write("This line is After Action execute!");
		//base.OnActionExecuted(filterContext);
	}
}

添加特性

同样的,添加特性使其生效

public class HomeController : Controller
{
	// GET: UserManage/Home
	[MyAction]
	public ActionResult Index()
	{
		Response.Write("Action Execut");
		return View();
	}
}

效果如下:

return 的 view() 是在 Action 完成后执行的,所以会先显示两个 filter 的结果,再返回 view(),而 Action 中的内容则在二者之间显示。

结果过滤器

同样继承自ActionFilterAttribute实现,并提供了在两个不同时间点执行代码的能力,分别在 结果执行前(On ResultExecuting)/结果执行后(OnResultExecuted) 执行相关操作。

创建结果过滤器

首先创建过滤器 MyResult.cs,同样的,在 Filter 文件夹下新建一个类,继承自 ActionFilterAttribute

public class MyResult: ActionFilterAttribute
{
    //结果执行前执行
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        filterContext.HttpContext.Response.Write("Before Result<bt />");
    }
    
    //结果执行后执行
    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        filterContext.HttpContext.Response.Write("After Result<bt />");
    }
}

添加特性

同样的,添加特性使其生效

public class HomeController : Controller
{
	// GET: UserManage/Home
	[MyResult]
	public ActionResult Index()
	{
		Response.Write("Action Execut");
		return View();
	}
}

效果如下:

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 接口仔也不是好当的,聊一聊前后端分离开发中后端接口设计规范

    随着互联网的高速发展,前端页面的展示、交互体验越来越灵活、炫丽,响应体验也要求越来越高,后端服务的高并发、高可用、高性能、高扩展等特性的要求也愈加苛刻,从而导致...

    江南一点雨
  • 云采用成功的10个最佳实践

    虽然将业务迁移到云平台是一件好事,但企业必须谨慎行事。无论企业是处理多个工作负载还是产品组合,从内部部署到基于云计算的IT转型不只是为了了解技术。而成功采用云计...

    静一
  • Laravel框架是什么

    Laravel是一个开源PHP框架,功能强大且易于理解。它遵循模型 - 视图 - 控制器设计模式(MVC)。Laravel重用了不同框架的现有组件,这有助于创...

    叫我可儿呀
  • 透彻分析:常见的前端架构风格和案例

    没多少人能记住上面的定义,需要注意的是本文不是专业讨论系统架构的文章,笔者也还没到那个水平. 所以暂时没必要纠结于什么是架构模式、什么是架构风格。在这里尚且把它...

    Nealyang
  • PHP中常用的七大框架的优点与缺点

    长期以来,PHPer一直在讨论各种PHP框架的优缺点,互联网上的信息相对分散。现在我收集并总结了几个主流框架,其中我只使用了yii2、laravel、YAF和T...

    叫我可儿呀
  • SpringMVC自学笔记

    1.<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-clas...

    阮键
  • 从Web开发者的视角来解读MVC架构

    原文标题:An Introduction to MVC Architecture: A Web Developer's Point of View,作者:Dip...

    Lemon黄
  • SpringBoot 拦截器

    web拦截器作用有权限控制,日志记录等等。SpringBoot 提供 HandlerInterceptor 方便我们开发;

    IT技术小咖
  • Java开发就业需要熟练使用哪些知识

    Java是当前互联网行业内的热门语言,不仅可以应用于Android和网站开发而且也广泛应用于金融服务、高频金融空间等领域。也正是因为高居不下的热度,越来越多的人...

    千锋哈尔滨IT培训
  • 重新学习MySQL数据库6:浅谈MySQL的中事务与锁

    本系列文章将整理到我在GitHub上的《Java面试指南》仓库,更多精彩内容请到我的仓库里查看

    Java技术江湖

扫码关注云+社区

领取腾讯云代金券