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
---------------------------------------
下一篇: 1081: 哥德巴赫猜想
推荐阅读
-
asp.net实现在非MVC中使用Razor模板引擎的方法
-
ASP.NET MVC中图表控件的使用方法
-
Spring MVC的文件上传和下载以及拦截器的使用实例
-
ASP.NET MVC3模板页的使用(2)
-
详解Spring MVC如何测试Controller(使用springmvc mock测试)
-
Java IO文件过滤器对命令设计模式的使用
-
ASP.NET MVC中HtmlHelper控件7个大类中各个控件使用详解
-
asp.net MVC利用ActionFilterAttribute过滤关键字的方法
-
Spring Boot使用过滤器和拦截器分别实现REST接口简易安全认证示例代码详解
-
ASP.NET MVC使用ActionFilterAttribute实现权限限制的方法(附demo源码下载)