我正在将异常记录到asp.net核心中的数据库。 MyDbContext使用HttpContextAccessor参数。因此,我将HttpContextAccessor发送到MyDbContext.cs以访问我的JWT。但是,我无法从Startup.cs访问HttpContextAccessor。我该如何实现?
Startup.cs
public static class ExceptionHelper
{
public static async Task AddApplicationError(this HttpResponse response, IExceptionHandlerFeature error, IHttpContextAccessor httpContextAccessor)
{
Log log = new Log();
log.Message = error.Error.Message;
MyDbContext context = new MyDbContext(null, httpContextAccessor);
UnitOfWork uow = new UnitOfWork(context);
uow.LogRepo.AddOrUpdate(log);
await uow.CompleteAsync(false);
}
}
ExceptionHelper.cs
public class MyDbContext : DbContext
{
private readonly IHttpContextAccessor _httpContextAccessor;
public MyDbContext(DbContextOptions<MyDbContext> options, IHttpContextAccessor httpContextAccessor)
: base(GetOptions())
{
_httpContextAccessor = httpContextAccessor;
}
private static DbContextOptions GetOptions()
{
return SqlServerDbContextOptionsExtensions.UseSqlServer(new DbContextOptionsBuilder(), "server=asd; database=; user id=asd; password=1234").Options;
}
public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = default(CancellationToken))
{
var token = _httpContextAccessor.HttpContext.Request.Headers["Authorization"];
var audits = AuditHelper.AddAuditLog(base.ChangeTracker, token);
return (await base.SaveChangesAsync(true, cancellationToken));
}
}
MyDbContext
{{1}}
答案 0 :(得分:4)
您可以将所需的任何内容注入Configure
方法中。您已经通过以下这一行将其添加到服务集合中:
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
因此,您所需要做的就是将其添加到方法的参数列表中,如下所示:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, IHttpContextAccessor accessor)
{
// make use of it here
}
顺便说一句:我还要指出,您在使用依赖项注入时在静态帮助器类中手动创建DbContext
实例的过程有点代码味道。
根据评论进行更新
为了整理一些东西,我将从更改启动方式开始,为您配置DbContext,如下所示:
public class Startup
{
private readonly IConfiguration configuration;
public Startup(IConfiguration configuration)
{
this.configuration = configuration;
}
public void ConfigureServices(IServiceCollection services)
{
// register other things here...
services.AddDbContext<DataContext>(o => o.UseSqlServer(
config.GetConnectionString("MyConnectionString") // from appsettings.json
));
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
// set up app here...
}
}
然后可以从.GetOptions()
中删除MyDbContext
方法,并将构造函数更改为:
public MyDbContext(DbContextOptions<MyDbContext> options, IHttpContextAccessor httpContextAccessor)
: base(options)
{
_httpContextAccessor = httpContextAccessor;
}
然后,将MyDbContext
的实例注入需要访问它的任何类中。问题是(据我所知)DI无法与静态类/方法配合使用,并且您正在HttpResponse
上使用扩展方法记录错误。
我认为最好创建一个类,该类负责记录与您的MyDbContext
相关的错误,并将其注入到Configure
方法中:
public class ErrorLogger
{
private MyDataContext db;
public ErrorLogger(MyDataContext db) => this.db = db;
public void LogError(IExceptionHandlerFeature error)
{
Log log = new Log();
log.Message = error.Error.Message;
UnitOfWork uow = new UnitOfWork(this.db);
uow.LogRepo.AddOrUpdate(log);
await uow.CompleteAsync(false);
}
}
像在其他事物上一样,在DI容器中注册它,然后将其注入Configure
而不是HTTP访问器中:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ErrorLogger logger)
{
app.UseExceptionHandler(builder => builder.Run(async context =>
{
var error = context.Features.Get<IExceptionHandlerFeature>();
logger.LogError(error);
await context.Response.WriteAsync(error.Error.Message);
}));
}
我还没有测试过,并且我对.UseExceptionHandler(...)
不熟悉,因为我使用应用程序见解来记录异常等(如果您没有看到它,请查看它)。要注意的一件事是依赖项的范围。默认情况下,您的DbContext将为Scoped
(我认为应该保持这种状态),这意味着您无法将其注入Singleton
对象中。