Skip to content

ASP.NET MVC ActionFilter 全局日志实践 ​

在前后端分离或移动端接口开发中,服务端记录详细的请求参数日志对于排查问题至关重要。通过自定义 ActionFilter,我们可以优雅地在请求执行前后自动记录入参、出参及执行耗时。

1. 核心实现:自定义日志过滤器 ​

通过继承 ActionFilterAttribute 并重写 OnActionExecuting 方法,可以在 Action 执行前捕获所有上下文信息。

csharp
public class LogActionFilter : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        // 1. 获取基础路由信息
        string controllerName = filterContext.RouteData.Values["controller"].ToString();
        string actionName = filterContext.RouteData.Values["action"].ToString();

        // 2. 提取请求详情
        var request = filterContext.HttpContext.Request;
        var reqData = new
        {
            Controller = controllerName,
            Action = actionName,
            HttpMethod = request.HttpMethod,
            Url = request.Url.AbsoluteUri,
            Query = request.Url.Query,
            // 关键:捕获 Action 参数(已由 MVC 绑定完成)
            ActionParameters = filterContext.ActionParameters,
            ClientIP = request.UserHostAddress
        };

        // 3. 记录日志 (推荐配合 Newtonsoft.Json 序列化)
        LogHelper.Info(JsonConvert.SerializeObject(reqData));

        base.OnActionExecuting(filterContext);
    }
}

2. 日志内容建议 ​

为了保证日志的可追溯性,建议至少记录以下字段:

  • 基础信息:Controller/Action 名称、HTTP 谓词(GET/POST)。
  • 请求参数:URL QueryString、Form 表单、以及 ActionParameters。
  • 环境信息:客户端 IP、浏览器 UserAgent。
  • 性能监控(可选):在 OnActionExecuted 中计算并记录接口总耗时。

3. 注册方式 ​

3.1 全局注册 (推荐) ​

在 Global.asax.cs 或 FilterConfig.cs 中注册,即可对所有 Action 生效。

csharp
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
    filters.Add(new LogActionFilter());
}

3.2 局部注册 ​

直接在 Controller 或具体 Action 上添加特性标记。

csharp
[LogActionFilter]
public ActionResult CreateOrder(OrderDto dto) { ... }

4. 常见问题与优化 ​

  • 性能影响:在高并发场景下,建议使用异步日志写入或消息队列缓冲,避免阻塞请求主线程。
  • 敏感信息屏蔽:在序列化参数时,应注意屏蔽密码、银行卡号等敏感字段。
  • 调试环境控制:可以通过 #if DEBUG 或配置开关,仅在测试环境下记录全量日志。

5. 参考资料 ​

方舟 · Ark