如何借助IActionFilter实现.NET Core站点访问数据记录与后台展示?
.NET Core 使用IActionFilter实现访问数据统计的具体方案
1. 定义访问记录存储实体
首先定义用于存储统计数据的实体类,适配你的数据库存储:
public class VisitRecord { public int Id { get; set; } /// <summary> /// 访客IP地址 /// </summary> public string IpAddress { get; set; } /// <summary> /// 访问的页面/接口路径 /// </summary> public string RequestPath { get; set; } /// <summary> /// 访问时间 /// </summary> public DateTime VisitTime { get; set; } = DateTime.Now; /// <summary> /// 登录用户ID,未登录为null /// </summary> public string? UserId { get; set; } /// <summary> /// 客户端UA标识,可选存储 /// </summary> public string? UserAgent { get; set; } }
建好实体后在你的DbContext中添加对应的DbSet配置,完成数据库迁移。
2. 实现自定义统计Filter
推荐使用异步IActionFilter实现,避免阻塞请求线程:
public class VisitStatisticsFilter : IAsyncActionFilter { private readonly YourDbContext _dbContext; // 依赖注入数据库上下文,也可替换为Redis、日志服务等其他存储介质 public VisitStatisticsFilter(YourDbContext dbContext) { _dbContext = dbContext; } public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) { // 执行Action前记录访问数据,不影响正常请求逻辑 var visitRecord = new VisitRecord { // 取真实访客IP,反向代理场景需额外处理X-Forwarded-For请求头 IpAddress = context.HttpContext.Connection.RemoteIpAddress?.ToString() ?? "未知IP", RequestPath = context.HttpContext.Request.Path.ToString(), UserId = context.HttpContext.User.FindFirstValue(System.Security.Claims.ClaimTypes.NameIdentifier), UserAgent = context.HttpContext.Request.Headers.UserAgent.ToString() }; _dbContext.VisitRecords.Add(visitRecord); await _dbContext.SaveChangesAsync(); // 执行原本的Action逻辑 var resultContext = await next(); // 如果需要记录请求是否成功、响应状态码等信息,可在next执行后补充逻辑 // visitRecord.StatusCode = resultContext.HttpContext.Response.StatusCode; // await _dbContext.SaveChangesAsync(); } }
3. 注册Filter生效
有两种注册方式可选,根据你的需求选择:
- 全局注册:所有Controller的Action都会触发统计逻辑
首先在Program.cs中注册Filter为Scoped服务(匹配DbContext的生命周期):
然后在控制器注册配置中添加全局Filter:builder.Services.AddScoped<VisitStatisticsFilter>();builder.Services.AddControllersWithViews(options => { options.Filters.AddService<VisitStatisticsFilter>(); }); - 局部注册:仅给需要统计的Controller/Action添加统计逻辑
先完成上面的Filter服务注册,然后在对应的Controller或Action上添加属性即可:[ServiceFilter(typeof(VisitStatisticsFilter))] public class HomeController : Controller { // Action逻辑 }
4. 管理后台数据统计查询示例
直接基于存储的VisitRecords表即可查询你需要的各类指标:
- 每日登录用户数查询示例:
// 查询指定日期的登录用户数 var targetDate = new DateTime(2024,5,20); var dailyLoginUserCount = await _dbContext.VisitRecords .Where(x => x.VisitTime.Date == targetDate.Date && x.UserId != null) .Select(x => x.UserId) .Distinct() .CountAsync(); - 页面访问量统计示例:
// 按访问量倒序取TOP10访问页面 var pageVisitRank = await _dbContext.VisitRecords .GroupBy(x => x.RequestPath) .Select(g => new { Path = g.Key, VisitCount = g.Count() }) .OrderByDescending(x => x.VisitCount) .Take(10) .ToListAsync(); - 每日独立访客数查询示例:
var dailyUv = await _dbContext.VisitRecords .Where(x => x.VisitTime.Date == targetDate.Date) .Select(x => x.IpAddress) .Distinct() .CountAsync();
注意事项
- 高流量场景下不建议每次请求直接写数据库,可先将访问数据写入Redis等缓存,定时批量同步到数据库,降低数据库压力
- 用Nginx、CDN等反向代理部署时,需要提前配置ForwardedHeaders中间件,才能正确获取到访客的真实IP,避免获取到代理服务器的IP
- Filter中尽量不要写同步阻塞逻辑,全部使用异步方法避免降低站点吞吐量
内容的提问来源于stack exchange,提问作者Cnrgrsc
相关产品推荐
相关产品推荐

