Can I access a database during middleware in ASP.NET Core?

Viewed 1435

I want to create Visitor page

private readonly DBDatacontext _db;
private RequestDelegate _requestDelegate;

public VisitorMiddleWare(RequestDelegate requestDelegate, DBDatacontext db)
{
    _requestDelegate = requestDelegate;
    _db = db;
}

public async Task InvokeAsync(HttpContext context)
{
    string visitorId = context.Request.Cookies["VisitorId"];
    string remoteIpAddress = context.Connection.RemoteIpAddress.ToString();

    if (visitorId == null)
    {
        context.Response.Cookies.Append("VisitorId", Guid.NewGuid().ToString(), new 
                  CookieOptions()
            {
                Path = "/",
                HttpOnly = true,
                Secure = false,
            });

        visitorId = context.Request.Cookies["VisitorId"];

        var model = new Visitor()
            {
                Ip = remoteIpAddress
            };

        _db.AddAsync(model);
        _db.SaveChangesAsync();
    }

    await _requestDelegate(context);
}

and in the startup

app.UseMiddleware(typeof(VisitorMidlleWare));

but I get this error:

Cannot resolve scoped service 'DBDatacontext' from root provider.

1 Answers

Your DB context is not a singleton so you should not resolve it in the constructor. You can add it instead as a parameter for InvokeAsync:

public async Task InvokeAsync(HttpContext context, DBDatacontext db)
{
}

By default an EF DB context is registered as Scoped, which by default means one is created per request. And you cannot make it a singleton because it is not thread-safe.

InvokeAsync can specify other parameters to get scoped and transient dependencies from the service collection. You can alternatively access the RequestServices property on the HttpContext to get services dynamically.

More on this and more on my blog ;) https://joonasw.net/view/aspnet-core-di-deep-dive

Use cases for each approach:

Constructor: Singleton components that are needed for all requests

Invoke parameter: Scoped and transient components that are always necessary on requests

RequestServices: Components that may or may not be needed based on runtime information

Related