MVC 过滤器使用 ActionFilterAttribute

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

大概的流程如下

通过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  。

wepi API 在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

 一、定义过滤器                                                                                                                                                                           

   /// <summary>
    /// 全局日志过滤器(在WebApiConfig中注册),每个action执行都会执行该过滤器
    /// </summary>
    public class LogAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(HttpActionContext filterContext)
        {
            if (!SkipLogging(filterContext))
            {
                //获取action名称
                string actionName = filterContext.ActionDescriptor.ActionName;
                //获取Controller 名称
                string controllerName = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName;
                //获取触发当前方法的Action方法的所有参数 
                var paramss = filterContext.ActionArguments;
                string Content = Newtonsoft.Json.JsonConvert.SerializeObject(paramss);


                LogHelper.GetInstance(" LogFilter").Write(string.Format("OnActionExecuting、控制器:{0},动作:{1},参数:{2}", controllerName, actionName, Content));
            }
            base.OnActionExecuting(filterContext);
        }


        public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
        {
            if (!SkipLogging(actionExecutedContext.ActionContext))
            {
                //获取action名称
                string actionName = actionExecutedContext.ActionContext.ActionDescriptor.ActionName;
                //获取Controller 名称
                string controllerName = actionExecutedContext.ActionContext.ActionDescriptor.ControllerDescriptor.ControllerName;
                //获取触发当前方法的Action方法的所有参数 
                var paramss = actionExecutedContext.ActionContext.ActionArguments;
                string Content = Newtonsoft.Json.JsonConvert.SerializeObject(paramss);


                LogHelper.GetInstance(" LogFilter").Write(string.Format("OnActionExecuted、控制器:{0},动作:{1},参数:{2}", controllerName, actionName, Content));
            }
            base.OnActionExecuted(actionExecutedContext);
        }




        /// <summary>
        /// 判断控制器和Action是否要进行拦截(通过判断是否有NoLogAttribute过滤器来验证)
        /// </summary>
        /// <param name="actionContext"></param>
        /// <returns></returns>
        private static bool SkipLogging(HttpActionContext actionContext)
        {
            return actionContext.ActionDescriptor.GetCustomAttributes<NoLogAttribute>().Any() || actionContext.ActionDescriptor.ControllerDescriptor.GetCustomAttributes<NoLogAttribute>().Any();
        }
    }


    /// <summary>
    /// 不需要日志记录的过滤器
    /// </summary>
    [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true)]
    public class NoLogAttribute : Attribute
    {


    }

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

 public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {

            config.Filters.Add(new LogAttribute());


            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{action}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );
        }
    }

三、在控制器中使用                                                                                                                                                                       

       // GET api/sodetails/5
        public string Get(int id)
        {
            return "{\"Value\":\"" + id + "\"}";
        }

        [NoLog]
        public string Post([FromBody]string value)  //该action不添加日志信息
        {
            return "{\"Value\":\"" + value + "\"}";
        }

四、日志效果                                                                                                                                                                                 

2018/5/14 14:11:11636619038710767426
L_Message : OnActionExecuting、控制器:SoDetails,动作:Get,参数:{"id":123}
L_Level : INFO
L_Folder :  LogFilter
L_CreatTime : 2018-05-14 14:11:11.075
L_ServerHostName : sh-ysl-bi-hzq
L_ServerHostIP : 10.10.40.5
---------------------------------------
2018/5/14 14:11:14636619038740781337
L_Message : OnActionExecuted、控制器:SoDetails,动作:Get,参数:{"id":123}
L_Level : INFO
L_Folder :  LogFilter
L_CreatTime : 2018-05-14 14:11:14.078
L_ServerHostName : sh-ysl-bi-hzq
L_ServerHostIP : 10.10.40.5
---------------------------------------




猜你喜欢

转载自blog.csdn.net/hezheqiang/article/details/80309060
今日推荐