ASP.NET MVC中实现按IP计时的文章浏览计数器
实现IP+文章的间隔式浏览计数器
要解决刷新就重复计数的问题,核心是追踪每个IP对单篇文章的最近访问时间,只有当距离上次访问超过设定间隔时,才增加浏览量。以下是具体实现方案:
1. 创建访问记录实体类
新增一个PostViewRecord类,用来存储每个IP访问文章的唯一记录:
public class PostViewRecord { // 复合主键:文章ID + 访问IP,避免同一IP对同一文章重复创建记录 public int PostId { get; set; } public string VisitorIp { get; set; } = string.Empty; // 最后访问时间,用于判断是否超过计数间隔 public DateTime LastVisitedTime { get; set; } // 关联文章实体(可选,根据你的数据库关系需求配置) public Post Post { get; set; } = null!; }
2. 配置DbContext
在你的数据库上下文类中添加访问记录的DbSet,并通过Fluent API配置复合主键:
public class YourDbContext : DbContext { public DbSet<Post> Posts { get; set; } public DbSet<PostViewRecord> PostViewRecords { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { // 配置PostViewRecord的复合主键 modelBuilder.Entity<PostViewRecord>() .HasKey(pvr => new { pvr.PostId, pvr.VisitorIp }); } }
3. 修改PostController的Detail方法
更新逻辑,先检查访问记录再决定是否增加浏览量:
public async Task<IActionResult> Detail(int id) { var post = await _postInterface.GetByIdAsync(id); if (post == null) { return NotFound(); } // 获取访问者IP(注意:如果网站在反向代理后,需配置ForwardedHeaders才能拿到真实IP) var visitorIp = Request.HttpContext.Connection.RemoteIpAddress?.ToString() ?? "Unknown"; // 设定计数间隔,比如24小时(可根据需求调整,也可放到配置文件中) var viewInterval = TimeSpan.FromHours(24); // 查询该IP最近是否访问过这篇文章 var existingRecord = await _context.PostViewRecords .FirstOrDefaultAsync(pvr => pvr.PostId == id && pvr.VisitorIp == visitorIp); if (existingRecord == null) { // 无访问记录:新增记录+增加浏览量 post.View++; _context.PostViewRecords.Add(new PostViewRecord { PostId = id, VisitorIp = visitorIp, LastVisitedTime = DateTime.UtcNow }); await _context.SaveChangesAsync(); } else { // 有记录:检查是否超过设定间隔 if (DateTime.UtcNow - existingRecord.LastVisitedTime > viewInterval) { post.View++; existingRecord.LastVisitedTime = DateTime.UtcNow; await _context.SaveChangesAsync(); } // 未超过间隔:不执行计数操作 } return View(post); }
额外注意事项
- 真实IP获取:如果网站部署在Nginx、Cloudflare等反向代理后面,默认拿到的是代理服务器的IP。需要在Startup/Program.cs中配置ForwardedHeaders:
app.UseForwardedHeaders(new ForwardedHeadersOptions { ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto }); - 间隔配置:可以把
viewInterval放到appsettings.json中,通过IConfiguration读取,方便后续无需改代码就能调整间隔。 - 性能优化:如果网站流量较大,可以考虑用Redis缓存访问记录,减少数据库查询和写入的压力。
内容的提问来源于stack exchange,提问作者ZNAXNOR
相关产品推荐
相关产品推荐

