MVC 过滤
我们来看两个接口:
public interface IActionFilter { // Methods void OnActionExecuted(ActionExecutedContext filterContext); void OnActionExecuting(ActionExecutingContext filterContext); }
public interface IResultFilter { // Methods void OnResultExecuted(ResultExecutedContext filterContext); void OnResultExecuting(ResultExecutingContext filterContext); }
这两个接口都有两个方法,分别表示视图加载前,视图加载后执行的方法。
ViewResult执行前,执行后的执行的方法。
我们自定义一个过滤器
public class DemoFilter:ActionFilterAttribute { public string Message { get; set; } public override void OnActionExecuted(ActionExecutedContext filterContext) { //在Action执行之后执行 输出到输出流中文字:After Action execute xxx filterContext.HttpContext.Response.Write(@"<br />After Action execute" + "\t " + Message); base.OnActionExecuted(filterContext); } public override void OnActionExecuting(ActionExecutingContext filterContext) { filterContext.HttpContext.Response.Write(@"<br />Before Action execute"+"\t "+ Message); base.OnActionExecuting(filterContext); } public override void OnResultExecuted(ResultExecutedContext filterContext) { //在Result执行之后 filterContext.HttpContext.Response.Write(@"<br />After ViewResult execute" + "\t " + Message); base.OnResultExecuted(filterContext); } public override void OnResultExecuting(ResultExecutingContext filterContext) { //在Result执行之前 filterContext.HttpContext.Response.Write(@"<br />Before ViewResult execute" + "\t " + Message); base.OnResultExecuting(filterContext); }
我们看看ActionFilterAttribute他为什么能重写这几个方法了:
public abstract class ActionFilterAttribute : FilterAttribute, IActionFilter, IResultFilter { // Methods protected ActionFilterAttribute(); public virtual void OnActionExecuted(ActionExecutedContext filterContext); public virtual void OnActionExecuting(ActionExecutingContext filterContext); public virtual void OnResultExecuted(ResultExecutedContext filterContext); public virtual void OnResultExecuting(ResultExecutingContext filterContext); }
原来他实现了IActionFilter, IResultFilter 两个接口
我们来创建一个控制器,index方法,并且打上过滤标签
[DemoFilter] public ActionResult Index() { this.ControllerContext.HttpContext.Response.Write(@"<br />Action execute"); return Content("<br/>Result Excut! "); }
我们执行这个视图,视图结果为:
先执行视图操作过滤,再执行ViewResult的过滤
当然我们也可以将这个过滤标签打在Controller上面,这样控制器下面的每个视图都会执行这个过滤操作
[DemoFilter] public class HomeController : Controller
假如我们想让这个过滤执行两次了,即在控制器上面执行一次,然后在视图上面在执行一次,你会说,我在控制器上面打上一个过滤标签,在视图上面再打一个过滤标签不就行了,但是结果还是执行一次,解决这个,我们知需要加上这句话:
[AttributeUsage(AttributeTargets.All, AllowMultiple = true)]
这样代码:
[AttributeUsage(AttributeTargets.All, AllowMultiple = true)] public class DemoFilter : ActionFilterAttribute
{
}
这样我们分别在homecontroller和视图index上面打上标签
[DemoFilter] public class HomeController : Controller { [DemoFilter] public ActionResult Index() { this.ControllerContext.HttpContext.Response.Write(@"<br />Action execute"); return Content("<br/>Result Excut! "); } }
会发现会执行两次:
我们有时候发现,这样一个个的写太麻烦了,想做一个全局过滤
我们只需要在Application_Start()添加一个全局过滤
GlobalFilters.Filters.Add(new DemoFilter() { Message = "Gloable" });
这样Application_Start()代码为:
protected void Application_Start() { AreaRegistration.RegisterAllAreas(); GlobalFilters.Filters.Add(new DemoFilter() { Message = "Gloable" }); RegisterGlobalFilters(GlobalFilters.Filters); RegisterRoutes(RouteTable.Routes); }
我们所有的控制器和视图都不加过滤标签,但是依旧执行了过滤。
标签过滤:
比如有时候我们需要判断是ajax请求或者别的请求等我们可以自己加上一个标签
标签定义为:
public class AjaxRequest:Attribute { }
public abstract class ActionFilterAttribute : FilterAttribute, IActionFilter, IResultFilter
ActionFilterAttribute继承FilterAttribute,而FilterAttribute的父类是Attribute
public abstract class FilterAttribute : Attribute, IMvcFilter
{
}
我们在DemoFilter的OnActionExecuting里面判断
public override void OnActionExecuting(ActionExecutingContext filterContext) { if (filterContext.ActionDescriptor.IsDefined(typeof(AjaxRequest), false)) { filterContext.Result = new ContentResult() { Content = "<br>直接跳过Action方法" }; } filterContext.HttpContext.Response.Write("不执行Action里面的方法"); base.OnActionExecuting(filterContext); }
我们在home控制器的index方法前面打上 [AjaxRequest]标签
[AjaxRequest] public ActionResult Index() { this.ControllerContext.HttpContext.Response.Write(@"<br />Action execute"); return View(); }
再运行我们发现结果为:
和前面的比较
不再执行action方法和onActionExcuted,但是会执行Result过滤器和生成视图