从.net Core WebApi中的startup.cs访问HttpContextAccessor

编程入门 行业动态 更新时间:2024-10-26 11:23:01
本文介绍了从 Core WebApi中的startup.cs访问HttpContextAccessor的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我正在将异常记录到asp核心中的数据库. MyDbContext使用HttpContextAccessor参数.因此,我将HttpContextAccessor发送到MyDbContext.cs以访问我的JWT.但是,我无法从Startup.cs访问HttpContextAccessor.我该如何实现?

I'm logging exceptions to database in asp core. MyDbContext take HttpContextAccessor parameter.So, I'm sending HttpContextAccessor to MyDbContext.cs for access my JWT. But, I can't access my HttpContextAccessor from Startup.cs. How can I achieve this?

Startup.cs

Startup.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

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

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

推荐答案

您可以将所需的任何内容注入Configure方法.您已经通过以下这一行将其添加到服务集合中:

You can inject whatever you need into the Configure method. You have already added it to the service collection with this line:

services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

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

So all you need to do is add it to the list of arguments on the method like this:

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

顺便说一句:我还要指出,当您使用依赖项注入时,您是在静态帮助器类中手动创建DbContext的实例,这有点代码味道.

As an aside: I would also point out that it's a bit of a code smell that you are manually creating an instance of your DbContext inside your static helper class when you are using dependency injection.

根据评论进行更新

为了整理一些东西,我将从更改启动方式开始,为您配置DbContext,如下所示:

In order to tidy things up a bit I would start by changing your startup to configure you DbContext something like this:

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()方法,并将构造函数更改为:

You can then remove the .GetOptions() method from MyDbContext, and change the constructor to:

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

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

Then you inject an instance of MyDbContext into whatever class needs access to it. The problem is that (to my knowledge) DI does not work well with static classes/methods, and you are using an extension method on the HttpResponse to log your error.

我认为最好创建一个类,该类负责记录错误并依赖于您的MyDbContext并将其注入到Configure方法中:

In my opinion it would be better to create a class that is responsible for logging the error with a dependency on your MyDbContext and have that injected into the Configure method:

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访问器中:

Register it with the DI container as you have with other things, then inject it into Configure instead of the HTTP accessor:

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对象中.

I have not tested this, and I am not familiar with .UseExceptionHandler(...) as I use application insights to log exceptions etc (take a look at it if you've not seen it). One thing to be aware of is the scope of your dependencies; your DbContext will be Scoped by default (and I think you should leave it that way), which means you cannot inject it into Singleton objects.

更多推荐

从.net Core WebApi中的startup.cs访问HttpContextAccessor

本文发布于:2023-11-14 14:05:52,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1587417.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:WebApi   Core   net   HttpContextAccessor   cs

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!