ASP.NET Core 2.1 MVC-将每个请求记录到数据库

时间:2019-01-02 15:41:15

标签: entity-framework logging asp.net-core-mvc configure asp.net-core-2.1

我想数据库记录我的应用处理每个请求所花费的时间,以及一些其他信息,例如接收到的每个请求的IP地址。

我已经添加了一个应用程序。在Startup.cs中使用步骤->将依赖项注入配置到我的dbcontext中。当以下代码触发并且我的MVC管道似乎正确触发时,我没有收到任何错误。

问题在于,涉及dbcontext的所有调用似乎都退出了代码。在下面的示例中,db.PageRequests.Add(pageRequest);导致代码退出。该页面仍然可以正常显示,但是当然会丢失响应中附加的任何内容。

我忍不住认为这是一个异步/线程问题,但是我迷失了主意。我还尝试使dbcontext交互既同步又异步,但这无济于事。

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ApplicationDbContext db)
    {
        app.Use(async (context, next) =>
        {
            var sw = new Stopwatch();
            sw.Start();
            await next.Invoke();
            sw.Stop();

            PageRequest pageRequest = new PageRequest()
            {
                ipAddress = context.Connection.RemoteIpAddress.ToString(),
                loadTime = sw.ElapsedMilliseconds
            };
            db.PageRequests.Add(pageRequest);  // this code exits and page is rendered.  Code below here is never fired.
            db.SaveChanges();

            await context.Response.WriteAsync("<p>" + sw.ElapsedMilliseconds.ToString() + "<p>");
            await context.Response.WriteAsync("<p>" + context.Connection.RemoteIpAddress + "<p>");
            await context.Response.WriteAsync("<p>" + context.Request.Host + context.Request.Path + context.Request.QueryString + "<p>");

        });
    // other app.use statements here
    }

1 个答案:

答案 0 :(得分:0)

我在Microsoft Documentation中发现一条注释,指出了正确的方向。

  

因为中间件是在应用启动时构建的,而不是按请求构建的,所以中间件构造函数使用的范围内的生存期服务不会在每次请求期间与其他依赖项注入类型共享。如果必须在中间件和其他类型之间共享作用域服务,请将这些服务添加到Invoke方法的签名中。

我相信,在应用启动后,注入到Configure方法中的dbcontext将不再可用,因此在每个请求期间都无法访问。 令人沮丧的是,它没有引发错误。

解决方案是将中间件委托移至一个类,并将上下文注入invoke方法。

以下是对我有用的代码:

public class Logging
{
    private readonly RequestDelegate _next;

    public Logging(RequestDelegate next)
    {
        _next = next;
    }

    public async Task InvokeAsync(HttpContext context, ApplicationDbContext db)
    {
        var sw = new Stopwatch();
        sw.Start();
        await _next(context);
        sw.Stop();

        PageRequest pageRequest = new PageRequest()
        {
            ipAddress = context.Connection.RemoteIpAddress.ToString(),
            loadTime = sw.ElapsedMilliseconds
        };
        await db.PageRequests.AddAsync(pageRequest); 
        db.SaveChanges();

        await context.Response.WriteAsync("<p>" + sw.ElapsedMilliseconds.ToString() + "<p>");
        await context.Response.WriteAsync("<p>" + context.Connection.RemoteIpAddress + "<p>");
        await context.Response.WriteAsync("<p>" + context.Request.Host + context.Request.Path + context.Request.QueryString + "<p>");
    }

}

public static class LoggingMiddlewareExtensions
{
    public static IApplicationBuilder UseLogging(
        this IApplicationBuilder builder)
    {
        return builder.UseMiddleware<Logging>();
    }
}`

然后可以将Use语句添加到Startup.cs->配置

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ApplicationDbContext db)
    {

        app.UseLogging();

    }