我需要将一个db上下文对象注入一个名为 AuthenticateClient 的自定义中间件,但是我得到了异常:
InvalidOperationException:无法解析作用域服务 ' LC.Tools.API.Data.ApiDbContext'来自root provider。
AuthenticateClient.cs :
public class AuthenticateClient
{
private readonly RequestDelegate _next;
private readonly ILogger _logger;
private readonly GenericUnitOfWork _worker;
public AuthenticateClient(RequestDelegate next, ApiDbContext db, IHttpContextAccessor httpContext, IHostingEnvironment env, ILoggerFactory loggerFactory, IOptions<Utility.LCLog.Settings> settings)
{
_next = next;
_logger = loggerFactory.CreateLogger(settings.Value.ApplicationName);
_worker = new GenericUnitOfWork(new AppHelper(httpContext, db, env));
}
public async Task Invoke(HttpContext context)
{
if (!context.Request.Headers.Keys.Contains("key") || !context.Request.Headers.Keys.Contains("pass"))
{
context.Response.StatusCode = 400;
await context.Response.WriteAsync("Key or Pass missing from request header values");
return;
}
else
{
Client client;
string key, pass;
key = context.Request.Headers["key"];
pass = context.Request.Headers["pass"];
client = await _worker.GetRepo<Client>().SingleOrDefault(clnt => clnt.Active && clnt.Key.Equals(key) && clnt.Password.Equals(pass));
if (client == null)
{
_logger.LogWarning("Client authentication failed", new string[] { "Key: " + key, "Password: " + pass, "Host: " + context.Request.Host });
context.Response.StatusCode = 401;
await context.Response.WriteAsync("Authentication failed");
return;
}
}
await _next.Invoke(context);
}
}
AuthenticateClientExtension.cs :
public static class AuthenticateClientExtension
{
public static IApplicationBuilder UseClientAuthentication(this IApplicationBuilder builder)
{
return builder.UseMiddleware<AuthenticateClient>();
}
}
Startup.cs :
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApiDbContext>(options => options.UseSqlServer(this.ConnectionString));
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddMvc();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IOptions<Settings> lclog)
{
loggerFactory.AddLCLog(lclog.Value);
app.UseClientAuthentication();
app.UseMvc();
}
ApiDbContext.cs :
public class ApiDbContext : DbContext, IApiDbContext
{
public ApiDbContext(DbContextOptions<ApiDbContext> options) : base(options) { }
protected override void OnModelCreating(ModelBuilder builder)
{
...
}
}
答案 0 :(得分:2)
解决方案是使用 IApplicationBuilder 创建范围和init ApiDbContext 并将其传递给中间件对象。我还改变了注册 ApiDbContext
的方式
<强> AuthenticateClientExtension.cs 强>:
public static class AuthenticateClientExtension
{
public static IApplicationBuilder UseClientAuthentication(this IApplicationBuilder builder)
{
var scope = builder.ApplicationServices.CreateScope();
ApiDbContext db = scope.ServiceProvider.GetRequiredService<ApiDbContext>();
return builder.UseMiddleware<AuthenticateClient>(db);
}
}
<强> Startup.cs 强>:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApiDbContext>(options => options.UseSqlServer(this.ConnectionString));
...
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IOptions<Settings> lclog)
{
...
app.UseClientAuthentication();
app.UseMvc();
}