博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

asp.net core 记录页面访问记录

Posted on 2025-04-02 16:30  火冰·瓶  阅读(19)  评论(0)    收藏  举报

方案 1:使用中间件

中间件适用于所有请求,它可以在请求进入 Controller 之前执行统计操作。

1. 创建 VisitMiddleware

public class VisitMiddleware
{
    private readonly RequestDelegate _next;
    private readonly IServiceScopeFactory _scopeFactory;
    private readonly TimeSpan _timeSpan = TimeSpan.FromHours(1);

    public VisitMiddleware(RequestDelegate next, IServiceScopeFactory scopeFactory)
    {
        _next = next;
        _scopeFactory = scopeFactory; // 用于创建独立的 `DbContext`
    }

    public async Task InvokeAsync(HttpContext context)
    {
        using (var scope = _scopeFactory.CreateScope())
        {
            var dbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
            string ipAddress = context.Connection.RemoteIpAddress?.ToString() ?? "Unknown";
            string pageUrl = context.Request.Path;

            var oneHourAgo = DateTime.Now - _timeSpan;
            var existingVisit = dbContext.PageVisits
                .Where(v => v.IpAddress == ipAddress && v.PageUrl == pageUrl && v.VisitTime >= oneHourAgo)
                .FirstOrDefault();

            if (existingVisit == null)
            {
                dbContext.PageVisits.Add(new PageVisit
                {
                    IpAddress = ipAddress,
                    PageUrl = pageUrl,
                    VisitTime = DateTime.Now
                });
                await dbContext.SaveChangesAsync();
            }
        }

        await _next(context); // 继续执行后续请求
    }
}

2. 注册中间件

Program.cs 添加:

app.UseMiddleware<VisitMiddleware>();

  

 

方案 2:使用 ActionFilter

ActionFilter 适用于 Controller 层,它比中间件更灵活,可以指定仅在某些 ControllerAction 上执行。

1. 创建 VisitActionFilter

using Microsoft.AspNetCore.Mvc.Filters;

public class VisitActionFilter : IActionFilter
{
    private readonly IServiceScopeFactory _scopeFactory;
    private readonly TimeSpan _timeSpan = TimeSpan.FromHours(1);

    public VisitActionFilter(IServiceScopeFactory scopeFactory)
    {
        _scopeFactory = scopeFactory;
    }

    public void OnActionExecuting(ActionExecutingContext context)
    {
        using (var scope = _scopeFactory.CreateScope())
        {
            var dbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
            string ipAddress = context.HttpContext.Connection.RemoteIpAddress?.ToString() ?? "Unknown";
            string pageUrl = context.HttpContext.Request.Path;

            var oneHourAgo = DateTime.UtcNow - _timeSpan;
            var existingVisit = dbContext.PageVisits
                .Where(v => v.IpAddress == ipAddress && v.PageUrl == pageUrl && v.VisitTime >= oneHourAgo)
                .FirstOrDefault();

            if (existingVisit == null)
            {
                dbContext.PageVisits.Add(new PageVisit
                {
                    IpAddress = ipAddress,
                    PageUrl = pageUrl,
                    VisitTime = DateTime.UtcNow
                });
                dbContext.SaveChanges();
            }
        }
    }

    public void OnActionExecuted(ActionExecutedContext context) { }
}

2. 注册 ActionFilter

Program.cs 中:

services.AddScoped<VisitActionFilter>();

然后,在 Controller 中使用:

[ServiceFilter(typeof(VisitActionFilter))]
public class MyController : ControllerBase
{
    // 所有请求自动记录访问
}

选哪种方案?

  • 中间件 (Middleware) 适用于 所有请求,不会局限于某个 Controller

  • 过滤器 (ActionFilter) 适用于 特定的 ControllerAction,如果你不想记录所有页面,可以选择这个方案。