曦远 (DealiAxy)一份私人的文字刊物

StarBlog
返回文章列表折页手记阅读全文
StarBlog博客开发笔记

StarBlog Development Notes (11): Implementing Visit Statistics

Series Articles Developing a Blog Project with .NetCore: StarBlog - (1) Why Write Your Own Blog? Developing a Blog Project with .NetCore: StarBlog - (2) Environment Setup and Project Creation Developing a Blog Project with .NetCore: StarBlog - (3) Model Design Developing a Blog Project with .NetCore: StarBlog - (4) Batch Import of Markdown Blog Posts Developing a Blog Project with .NetCore: StarBl

曦远 (DealiAxy)约 15 分钟
目录7 个章节

Series Articles

Preface

Back from the Dragon Boat Festival holiday, my blog still isn't live. Seeing how well all the experts' sites are doing, I feel a faint sense of urgency—time to hurry up and write some code~!

The previous articles have already implemented the basic features of the blog site. We're just one step away from going live, but there are still some minor details that have a big impact on site operations or user experience and must be completed, such as:

  • Site visit statistics
  • Image hosting

In that order, this article will first solve the visit statistics problem.

When it comes to visit statistics, the well-known options are Google Analytics or Baidu Analytics. The former can't be used in China, so the latter should be the only choice. But considering the feature gap between the two as well as that company's reputation, for my little site, I'd rather implement one myself~

Implementation

It shouldn't be hard to implement. To enable statistics and analysis, we first need to record data. The recorded content includes the user's IP, device, visit path, and visit time. Then, by analyzing this data, we can get the view/visit counts for each article, image, and category.

To record this data, we need to process every request the user makes. In AspNetCore there are several implementations, such as Filter, such as Middleware

Here I chose the middleware approach

PS: I saw an article online about implementing visit statistics in Django. The author wrote a method and called it once in every endpoint—it made my scalp tingle

Inject the Repo in the middleware, then on every request save the IP, device, request path, and other data to the database. This looks like it would have some impact on performance, but considering a blog site's concurrency should be quite small, the resulting performance loss should be negligible. (To be honest, I'm just being lazy)

We'll optimize later if we hit a performance bottleneck~

Model Definition

Create a new VisitRecord.cs in StarBlog.Data/Models

To save space, comments and such aren't included; see github for the full code

public class VisitRecord {
    public int Id { get; set; }
    public string Ip { get; set; }
    public string RequestPath { get; set; }
    public string? RequestQueryString { get; set; }
    public string RequestMethod { get; set; }
    public string UserAgent { get; set; }
    public DateTime Time { get; set; }
}

Write a Middleware

Create a new VisitRecordMiddleware.cs in StarBlog.Web/Middlewares

public class VisitRecordMiddleware {
    private readonly RequestDelegate _next;

    public VisitRecordMiddleware(RequestDelegate requestDelegate) {
        _next = requestDelegate;
    }

    public Task Invoke(HttpContext context, IBaseRepository<VisitRecord> visitRecordRepo) {
        var request = context.Request;
        var response = context.Response;

        visitRecordRepo.InsertAsync(new VisitRecord {
            Ip = context.Connection.RemoteIpAddress?.ToString().Split(":").Last(),
            RequestPath = request.Path,
            RequestQueryString = request.QueryString.Value,
            RequestMethod = request.Method,
            UserAgent = request.Headers.UserAgent,
            Time = DateTime.Now
        });
        
        return _next(context);
    }
}

There's one thing to note here: my visitRecordRepo is injected in the Invoke method. Why not inject it in the constructor?

Because the constructor of an AspNetCore middleware is Singleton, so it can only inject Singleton services, while FreeSQL's Repository is Scoped. Injecting it in the constructor would throw an error

So it can only be injected in the Invoke method~

Using the Middleware

Edit StarBlog.Web/Programs.cs and add the middleware configuration

app.UseMiddleware<VisitRecordMiddleware>();

PS: This project is based on .Net6, where Startup and Program have been merged into one; if you're on .NetCore 3.1 or below, configure the middleware in Startup.cs.

Results

I haven't done any analysis based on the visit records yet, so I can only screenshot the database

image-20220606174923532

OK, next we can analyze this data (I'll write about that later in the admin backend development section)

_EOF_

StarBlog Development Notes (11): Implementing Visit Statistics

本文作者:
程序设计实验室
版权声明:
本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!

相关文章

StarBlog博客开发笔记(1):项目介绍

前言 OK,我也来造轮子了 博客系统从一开始用WordPress,再到后来用hexo、hugo之类的静态博客生成放github托管,一直在折腾 折腾是为了更好解决问题,最终还是打算自己花时间搞一个好了 本系列文章将记录博客的开发过程~ 后端基于最新的.Net6和Asp.Net Core框架,遵循RESTFul接口规范,前端基于Vue+ElementUI开发,可作为 .Net Core 入门项目学习

2022-04-05 · StarBlog博客开发笔记 · 约 1 分钟

讨论

共 0 条

良言一句三冬暖,恶语伤人六月寒。

加载评论中…