MVC 过滤器使用 ActionFilterAttribute

         在asp.net mvc 中 webapi 和 mvc 处理消息是两个不同的管道,Asp.net mvc 和 webapi 为我们提供的 ActionFilterAttribute 拦截器,通过 重写 OnActionExecuting,来 拦截action的请求消息,当执行OnActionExecuting完成以后才真正进入请求的action中,action运行完后又把控制权给了 OnActionExecuted,这个管道机制可以使我们用它来轻松实现 权限认证、日志记录 ,跨域以及很多需要对全局或者部分请求做手脚的的功能。

大概的流程如下

MVC 过滤器使用 ActionFilterAttribute_第1张图片

通过ActionFilterAttribute ,就能拦截action 处理的所有内容,包括请求提交的参数以及返回值。由于asp.net MVC 与webapi  是两个完全独立的管道:

  • MVC由System.Web.Mvc.ActionFilterAttribute 来做action请求的拦截。
  • webapi 由 System.Web.Http.Filters.ActionFilterAttribute 来处理。

因此拦截action请求是完全不相干的两个通道,于此同时,当我们需要注册全局的ActionFilterAttribute  这两个也是分开注册的:

MVC 直接在System.Web.Mvc.GlobalFilterCollection  这个全局管道里面注册 ActionFilter ,位置在App_Start目录>FilterConfig 类>RegisterGlobalFilters 方法 使用参数filters , filters.Add(new YourMvcAttribute()) 添加你的mvc ActionFilterAttribute  。

WebAPI 在System.Web.Http.Filters 中注册, 在项目的App_Start 目录>WebApiConfig类中>Register 方法中加入使用 config参数, config.Filters.Add(new YourWebApiAttribute()); 添加你的 webapi ActionFilterAttribute 

这样就可以注册你的 ActionFilterAttribute   成为全局的Filter,系统中请求经过Action 之前或之后 都会被你的ActionFilter 拦下来做处理然后在转交下去。

好了道理已经讲完了,现在开始我自己要实现的 日志记录功能,

需求是记录所有访问webapi action的(请求地址、内容、访问用户、提交的参数、返回的结果、以及一些客户端的信息)

由于MVC 框架 提倡契约编程,在你自定义的Attribute 时,需要遵守契约规范, 【YourFilterName】+Attribute ,所以我的filter名字为  LogAttribute

 一、定义过滤器                                                                                                                                                                           

  1.    ///
  2.     /// 全局日志过滤器(在WebApiConfig中注册),每个action执行都会执行该过滤器
  3.     ///
  4.     public class LogAttribute : ActionFilterAttribute
  5.     {
  6.         public override void OnActionExecuting(HttpActionContext filterContext)
  7.         {
  8.             if (!SkipLogging(filterContext))
  9.             {
  10.                 //获取action名称
  11.                 string actionName = filterContext.ActionDescriptor.ActionName;
  12.                 //获取Controller 名称
  13.                 string controllerName = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName;
  14.                 //获取触发当前方法的Action方法的所有参数 
  15.                 var paramss = filterContext.ActionArguments;
  16.                 string Content = Newtonsoft.Json.JsonConvert.SerializeObject(paramss);
  17.  
  18.  
  19.                 LogHelper.GetInstance(" LogFilter").Write(string.Format("OnActionExecuting、控制器:{0},动作:{1},参数:{2}", controllerName, actionName, Content));
  20.             }
  21.             base.OnActionExecuting(filterContext);
  22.         }
  23.  
  24.  
  25.         public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
  26.         {
  27.             if (!SkipLogging(actionExecutedContext.ActionContext))
  28.             {
  29.                 //获取action名称
  30.                 string actionName = actionExecutedContext.ActionContext.ActionDescriptor.ActionName;
  31.                 //获取Controller 名称
  32.                 string controllerName = actionExecutedContext.ActionContext.ActionDescriptor.ControllerDescriptor.ControllerName;
  33.                 //获取触发当前方法的Action方法的所有参数 
  34.                 var paramss = actionExecutedContext.ActionContext.ActionArguments;
  35.                 string Content = Newtonsoft.Json.JsonConvert.SerializeObject(paramss);
  36.  
  37.  
  38.                 LogHelper.GetInstance(" LogFilter").Write(string.Format("OnActionExecuted、控制器:{0},动作:{1},参数:{2}", controllerName, actionName, Content));
  39.             }
  40.             base.OnActionExecuted(actionExecutedContext);
  41.         }
  42.  
  43.  
  44.  
  45.  
  46.         ///
  47.         /// 判断控制器和Action是否要进行拦截(通过判断是否有NoLogAttribute过滤器来验证)
  48.         ///
  49.         ///
  50.         ///
  51.         private static bool SkipLogging(HttpActionContext actionContext)
  52.         {
  53.             return actionContext.ActionDescriptor.GetCustomAttributes().Any() || actionContext.ActionDescriptor.ControllerDescriptor.GetCustomAttributes().Any();
  54.         }
  55.     }
  56.  
  57.  
  58.     ///
  59.     /// 不需要日志记录的过滤器
  60.     ///
  61.     [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true)]
  62.     public class NoLogAttribute : Attribute
  63.     {
  64.  
  65.  
  66.     }

二、在WebApiConfig.cs中注册全局过滤器                                                                                                                       

  1.  public static class WebApiConfig
  2.     {
  3.         public static void Register(HttpConfiguration config)
  4.         {
  5.  
  6.             config.Filters.Add(new LogAttribute());
  7.  
  8.  
  9.             config.Routes.MapHttpRoute(
  10.                 name: "DefaultApi",
  11.                 routeTemplate: "api/{controller}/{action}/{id}",
  12.                 defaults: new { id = RouteParameter.Optional }
  13.             );
  14.         }
  15.     }

三、在控制器中使用                                                                                                                                                                       

  1.        // GET api/sodetails/5
  2.         public string Get(int id)
  3.         {
  4.             return "{\"Value\":\"" + id + "\"}";
  5.         }
  6.  
  7.         [NoLog]
  8.         public string Post([FromBody]string value)  //该action不添加日志信息
  9.         {
  10.             return "{\"Value\":\"" + value + "\"}";
  11.         }

四、日志效果                                                                                                                                                                                 

  1. 2018/5/14 14:11:11636619038710767426
  2. L_Message : OnActionExecuting、控制器:SoDetails,动作:Get,参数:{"id":123}
  3. L_Level : INFO
  4. L_Folder :  LogFilter
  5. L_CreatTime : 2018-05-14 14:11:11.075
  6. L_ServerHostName : sh-ysl-bi-hzq
  7. L_ServerHostIP : 10.10.40.5
  8. ---------------------------------------
  9. 2018/5/14 14:11:14636619038740781337
  10. L_Message : OnActionExecuted、控制器:SoDetails,动作:Get,参数:{"id":123}
  11. L_Level : INFO
  12. L_Folder :  LogFilter
  13. L_CreatTime : 2018-05-14 14:11:14.078
  14. L_ServerHostName : sh-ysl-bi-hzq
  15. L_ServerHostIP : 10.10.40.5
  16. ---------------------------------------

 

全局过滤器 

https://www.cnblogs.com/hnsongbiao/p/8717553.html

有时我们想有些公共的方法需要每个Action都执行,但是又不想再每一个Controller上都打上Action标签,怎么办?幸好Asp。Net MVC3带

复制代码

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            filters.Add(new HandleErrorAttribute());
            //注册全局过滤器
            filters.Add(new TestFilterAttribute() { Message="全局"});
        }

复制代码

 这样就每个Action都会执行此过滤器,而不必每个Controller顶部都加上标签。

注意:如前面所述,在WebAPI中则是在System.Web.Http.Filters 中注册, 在项目的App_Start 目录>WebApiConfig类中>Register 方法中加入使用 config参数, config.Filters.Add(new YourWebApiAttribute()); 添加你的 webapi ActionFilterAttribute 

这样就可以注册你的 ActionFilterAttribute   成为全局的Filter

 

你可能感兴趣的:(.Net,Filter)