MVC 扩展FilterAttribute

本文详细介绍了ASP.NET MVC中ActionFilterAttribute的扩展与使用,包括如何自定义过滤器、实现IActionFilter和IResultFilter接口,以及在控制器和Action上的应用。此外,还讨论了异常过滤器HandleErrorAttribute的使用,以及全局和局部注册过滤器的方法。重点探讨了过滤器在日志记录、数据压缩等方面的作用,以及如何处理异常情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

MVC的行为过滤器特性(FilterAttribute)扩展

  1. 扩展ActionFilterAttribute
  2. 扩展IActionFilter

扩展ActionFilterAttribute

其内部依然是实现了IActionFilter的接口,并以虚函数可重写的形式进行.如下:

    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)]
    public abstract class ActionFilterAttribute : FilterAttribute, IActionFilter, IResultFilter
    {
     
        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);
    }

该基类ActionFilterAttribute实现了IActionFilterIResultFilter两个接口.
如下:


public interface IActionFilter
{
   
    void OnActionExecuted(ActionExecutedContext filterContext);
    
    void OnActionExecuting(ActionExecutingContext filterContext);
}

public interface IResultFilter
 {
 
     void OnResultExecuted(ResultExecutedContext filterContext);
    
     void OnResultExecuting(ResultExecutingContext filterContext);
 }


两个接口中的函数

  • Action 在执行控制器方法中和方法后进行调用.
  • Result在渲染前端视图中和选然后调用.
public class CustomActionFilterAttribute:ActionFilterAttribute
    {
        public override void OnActionExecuted(ActionExecutedContext filterContext)
        {
            cw($"{DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")}OnActionExecuted");
        }

        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            cw($"{DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")}OnActionExecuting");
        }

        public override void OnResultExecuted(ResultExecutedContext filterContext)
        {
            cw($"{DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")}OnResultExecuted");
        }

        public override void OnResultExecuting(ResultExecutingContext filterContext)
        {
            cw($"{DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")}OnResultExecuting");
        }
    }

运行过程中顺序是:OnActionExecuting->执行控制器->OnActionExecuted->OnResultExecuting->渲染视图->OnResultExecuted

IActionFilter和IResultFilter

其实上述的两个Attribute都是实现了这两个接口,由于是特性,所以仅仅继承Attribute是无效的.

无效

public class CustomActionFilterAttribute2 : /*Filter*/Attribute, IActionFilter
    {
        public void OnActionExecuted(ActionExecutedContext filterContext)
        {
            cw($"{DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")}OnActionExecuted");
        }

        public void OnActionExecuting(ActionExecutingContext filterContext)
        {
            cw($"{DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")}OnActionExecuting");
        }
    }

其原因在于这里Attribute是继承自FilterAttribute,又实现了IMvcFilter接口.

能干啥?

日志记录,任何一个位置都会有不可预料的错误发生.最重要的是,浏览器和服务器在进行请求响应操作时,是需要一定的数据传送的.传送的长短就会直观反映到响应的速度上.

在需要关注点的位置上进行编写.
数据压缩上,那就是在执行OnActionExecuting时要做的.

public void OnActionExecuting(ActionExecutingContext filterContext)
{
     //获取浏览器和服务器同时支持的压缩规则.
     var request=filterContext.HttpContext.Request;
     var response=filterContext.HttpContext.Response;
     //获取浏览器支持的压缩格式.
	string accept_ecode=request.Headers["Accept-Encoding"];
	if(!string.IsNullOrWhiteSpace(accept_ecode)&&accept_ecode.ToUpper().Contains("GZIP")){
		response.AddHeader("Content-Encoding","gzip");//设置服务器响应头解压方式.
		response.Filter=new GZipStream(response.Filter,CompressionMode.Compress);//压缩类型指定.

	//日志记录.log4net
	            myLogger.Info($"{DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")}OnActionExecuting");

	}
}

属性的注册方式

  1. 全局注册(在App_Start/FilterConfig.cs进行)
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            //filters.Add(new HandleErrorAttribute());
            //整个项目都将应用.
            filters.Add(new CustomActionFilterAttribute());
        }
    
  2. 标记在控制器上(所有Action都将应用)
    [CustomActionFilterAttribute]
    public class CustomController{}
    
  3. 标记在Action上.只对此action生效.

ExceptionFilter

异常Filter
常规操作:try-catch包裹,代码冗余.

  1. HandlerErrorAttribute
  2. IExceptionFilter

HandleErrorAttribute扩展

重写或实现

public virtual void OnException(ExceptionContext filterContext){
	if(!filterContext.ExceptionHandler){
		//处理异常.
		//1.如果是访问页面,展示一个页面出去,报出异常消息.
		//2.ajax请求,响应一个json格式的数据出去.
		if(filterContext.HttpContext.Request.IsAjaxRequest()){//是否为Ajax请求.
		filterContext.Result=new JsonResult(){
			Data=new{
				DebugMessage=filterContext.Exception.Message,
				RetValue="",
				PromptMsg="发生错误,请联系管理员"
			}
		};
	}
	else{
		filterContext.Result=new ViewResult(){
			ViewName="",//指定错误页面.
			ViewData=new ViewDataDictionary<string>(filterContext.Exception.Message)//错误消息.
		};
	}
	filterContext.ExceptionHandler=true;
}

但依然会存在异常捕捉不到的,上面的更偏向于业务异常方面.若访问一个不该访问的页面,上述方法页无能为力了.

需要在Global.asax(全局处理)中进行

///响应!=200,被这里捕捉.
protected void App_err(object s,EventArgs e){
	Exception ex=Server.GetLastError();//获取最后的响应错误.
	Response.Write();//返回一个错误页面.
	Server.ClearError();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值