gpt4 book ai didi

c# - 在 .net Core WebApi 中从 startup.cs 访问 HttpContextAccessor

转载 作者:行者123 更新时间:2023-11-30 19:52:52 24 4
gpt4 key购买 nike

我正在将异常记录到 asp.net core 中的数据库。 MyDbContext 采用 HttpContextAccessor 参数。因此,我将 HttpContextAccessor 发送到 MyDbContext.cs 以访问我的 JWT。但是,我无法从 Startup.cs 访问我的 HttpContextAccessor。我怎样才能做到这一点?

启动.cs

   public void ConfigureServices(IServiceCollection services)
{
services.AddHttpContextAccessor();
services.AddMvc();
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddDbContext<MyDbContext>();
services.AddTransient<IUnitOfWork, UnitOfWork>();
}


public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseExceptionHandler(builder => builder.Run(async context =>
{
var error = context.Features.Get<IExceptionHandlerFeature>();

context.Response.AddApplicationError(error,???????);//I want access HttpContextAccessor
await context.Response.WriteAsync(error.Error.Message);
}));

app.UseHttpsRedirection();
app.UseMvc();
}

ExceptionHelper.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);
}
}

MyDbContext

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));
}
}

最佳答案

您可以将所需的任何内容注入(inject)Configure 方法。您已经使用此行将其添加到服务集合中:

services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

所以您需要做的就是将它添加到方法的参数列表中,如下所示:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, IHttpContextAccessor accessor)
{
// make use of it here
}

顺便说一句:我还要指出,当您使用依赖项注入(inject)时,您在静态帮助程序类中手动创建 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...
}
}

然后您可以从 MyDbContext 中删除 .GetOptions() 方法,并将构造函数更改为:

public MyDbContext(DbContextOptions<MyDbContext> options, IHttpContextAccessor httpContextAccessor)
: base(options)
{
_httpContextAccessor = httpContextAccessor;
}

然后将 MyDbContext 的实例注入(inject)到任何需要访问它的类中。问题是(据我所知)DI 不能很好地与静态类/方法一起使用,并且您正在 HttpResponse 上使用扩展方法来记录您的错误。

在我看来,最好创建一个类来记录依赖于 MyDbContext 的错误,并将其注入(inject)到 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 容器注册它,然后将它注入(inject) 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(...),因为我使用 application insights 来记录异常等(如果您还没有看到,请查看它它)。需要注意的一件事是依赖项的范围;默认情况下,您的 DbContext 将被 Scoped(我认为您应该保持这种状态),这意味着您不能将其注入(inject) Singleton 对象。

关于c# - 在 .net Core WebApi 中从 startup.cs 访问 HttpContextAccessor,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52927463/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com