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

2024-06-19

我正在将异常记录到 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();
    }

异常助手.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);               
        }
    }

我的DbContext

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方法。您已经使用以下行将其添加到服务集合中:

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

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对象。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

从.net Core WebApi中的startup.cs访问HttpContextAccessor 的相关文章

  • 使用内联函数有什么问题?

    虽然在某些情况下使用内联函数会非常方便 内联函数有什么缺点吗 结论 显然 使用内联函数没有任何问题 但值得注意的是以下几点 过度使用内联实际上会使程序变慢 根据函数的大小 内联它可能会导致代码大小增加或减少 内联一个非常小的访问器函数通常会
  • C++ 用宏替换函数

    我们的 C 代码中有一个现有的函数实现 void Function int param printf In Function n int main Function 10 return 0 我希望将其更改为调用另一个函数 通过宏声明的帮助
  • Xamarin.Forms 中的 SignalR

    我正在尝试为 SignalR 创建 Xamarin Forms PCL 客户端 我发现的每个教程都是如何将 SignalR 添加到 Xamarin Android 或 Xamarin iOS 如何将 SignalR 添加到 Xamarin
  • 以编程方式创建一个包含 Web 部件的 Web 部件页面

    我想创建几个包含自定义 Web 部件的 Web 部件页面 以编程方式 我在互联网上搜索过 但找不到任何可以开始工作的东西 这是到目前为止我的代码 我在其中创建欢迎页面 而不是 Web 部件页面 using SPSite site new S
  • 在运行时从调试可视化工具中检测源语言

    我正在写一个Visual Studio 的调试可视化工具 https github com zspitz ExpressionToString visual studio debugger visualizer for expression
  • c和java语言中的换行符

    现在行分隔符取决于系统 但在 C 程序中我使用 n 作为行分隔符 无论我在 Windows 还是 Linux 中运行它都可以正常工作 为什么 在java中 我们必须使用 n 因为它与系统相关 那么为什么我们在c中使用 n 作为新行 而不管我
  • 如何在 C++ 中的文件末尾添加数据?

    我已按照网上的说明进行操作 此代码应该将输入添加到文件 数据库 的末尾 但当我检查时 数据会覆盖现有数据 请帮忙 这是我的代码 int main string name string address string handphone cou
  • 在 C# 中创建具有单独列的分隔文本

    我一直在尝试在 C 中创建一个制表符限制的文本文件 以便数据正确显示在单独的列中 Firstname Lastname Age John Smith 17 James Sawyer 31 我尝试过 t 字符 但我得到的只是 Firstnam
  • 使用Physics.Raycast 和Physics2D.Raycast 检测对象上的点击

    我的场景中有一个空的游戏对象 带有 2D 组件盒碰撞器 我将脚本附加到该游戏对象 void OnMouseDown Debug Log clic 但是当我点击我的游戏对象时 没有任何效果 你有什么想法 如何检测我的盒子碰撞器上的点击 使用光
  • 启动时出现 OData v4 错误:找不到段“Whatever”的资源

    我正在构建新的 v4 服务 一切进展顺利 直到我为新模型 实体添加了新控制器 并在启动站点进行测试运行时收到此错误 控制器似乎编码正确 就像其他控制器一样 控制器 CustomersOData 中的操作 GetFeed 上的路径模板 Cus
  • 互斥体实现可以互换(独立于线程实现)

    所有互斥体实现最终都会调用相同的基本系统 硬件调用吗 这意味着它们可以互换吗 具体来说 如果我使用 gnu parallel算法 使用openmp 并且我想让他们称之为线程安全的类我可以使用boost mutex用于锁定 或者我必须编写自己
  • ASP.NET:获取自 1970 年 1 月 1 日以来的毫秒数

    我有一个 ASP NET VB NET 日期 我试图获取自 1970 年 1 月 1 日以来的毫秒数 我尝试在 MSDN 中寻找方法 但找不到任何东西 有谁知道如何做到这一点 从 NET 4 6 开始 该方法ToUnixTimeMillis
  • 单击 form2 上的按钮触发 form 1 中的方法

    我对 Windows 窗体很陌生 我想知道是否可以通过单击表单 2 中的按钮来触发表单 1 中的方法 我的表格 1 有一个组合框 我的 Form 2 有一个 保存 按钮 我想要实现的是 当用户单击表单 2 中的 保存 时 我需要检查表单 1
  • Rx 中是否有与 Task.ContinueWith 运算符等效的操作?

    Rx 中是否有与 Task ContinueWith 运算符等效的操作 我正在将 Rx 与 Silverlight 一起使用 我正在使用 FromAsyncPattern 方法进行两个 Web 服务调用 并且我想这样做同步地 var o1
  • 未定义的行为或误报

    我 基本上 在野外遇到过以下情况 x x 5 显然 它可以在早期版本的 gcc 下编译干净 在 gcc 4 5 1 下生成警告 据我所知 警告是由 Wsequence point 生成的 所以我的问题是 这是否违反了标准中关于在序列点之间操
  • C++:.bmp 到文件中的字节数组

    是的 我已经解决了与此相关的其他问题 但我发现它们没有太大帮助 他们提供了一些帮助 但我仍然有点困惑 所以这是我需要做的 我们有一个 132x65 的屏幕 我有一个 132x65 的 bmp 我想遍历 bmp 并将其分成小的 1x8 列以获
  • 如何使用 watin 中的 FileUploadDialogHandler 访问文件上传对话框

    我正在使用 IE8 和 watin 并尝试通过我的网页测试上传文件 我不能简单地使用 set 方法设置上传文件 例如 ie FileUpload Find ById someId Set C Desktop image jpg 因为上传文本
  • 使用 Moq 使用内部构造函数模拟类型

    我正在尝试模拟 Microsoft Sync Framework 中的一个类 它只有一个内部构造函数 当我尝试以下操作时 var fullEnumerationContextMock new Mock
  • 如何编写一个同时需要请求和响应Dtos的ServiceStack插件

    我需要提供本地化数据服务 所有本地化的响应 Dto 都共享相同的属性 IE 我定义了一个接口 ILocalizedDto 来标记那些 Dto 在请求端 有一个ILocalizedRequest对于需要本地化的请求 Using IPlugin
  • 私有模板函数

    我有一堂课 C h class C private template

随机推荐