注入单例依赖项时,HttpContext 为空

Posted

技术标签:

【中文标题】注入单例依赖项时,HttpContext 为空【英文标题】:HttpContext is null when injected into a singleton dependency 【发布时间】:2021-07-11 19:45:27 【问题描述】:

我希望在我的 Blazor 应用程序中创建一个全局类,该类包含一个函数,该函数通过我从 Windows 身份验证获得的用户用户名获取用户的部门,但我似乎无法通过我的全局访问 HttpContextAccessor班级。当我注入它时,它就像它可以访问HttpContext,但是当它运行时,我得到了错误

System.NullReferenceException: '对象引用未设置为对象的实例。'

当你在局部变量中查看访问器时,访问器为空。

我进行了很多谷歌搜索,但找不到任何与我正在做的事情以及我目前对这些事情如何运作的了解很好地融合在一起的东西。

这是我的全局类:

public class Global

    [Inject]
    IHttpContextAccessor HttpContextAccessor  get; set; 

    public string Identity;
    public string Department;

    public Global()
    
        Identity = HttpContextAccessor.HttpContext.User.Identity.Name;
        
        CalculateDepartment(Identity)
    

    private void CalculateDepartment (string identity) 
        //Calculate what department the person is in based on user ID
        Department = CalculatedDepartment;
    

这是我的启动:

public class Startup

    public Startup(IConfiguration configuration)
    
        Configuration = configuration;
    

    public IConfiguration Configuration  get; 

    public void ConfigureServices(IServiceCollection services)
    
        services.AddRazorPages();
        services.AddServerSideBlazor(o => o.DetailedErrors = true);
        services.AddTelerikBlazor();
        services.AddHttpContextAccessor();
        services.AddSingleton<Global>();
    

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    
        if (env.IsDevelopment())
        
            app.UseDeveloperExceptionPage();
        
        else
        
            app.UseExceptionHandler("/Error");
            app.UseHsts();
        

        app.ApplicationServices.GetRequiredService<Global>();
        app.UseHttpsRedirection();
        app.UseStaticFiles();

        app.UseRouting();

        app.UseEndpoints(endpoints =>
        
            endpoints.MapDefaultControllerRoute();
            endpoints.MapControllers();

            endpoints.MapBlazorHub();
            endpoints.MapFallbackToPage("/_Host");
        );
    

Google 说要使用 services.AddScoped&lt;Global&gt;,但我发现这不适用于我的 CalculateDepartment 函数,当我使用 services.AddSingleton&lt;Global&gt; 时它起作用了,所以我一直这样。

它似乎对我尝试以这种方式注入此文件的任何内容执行此操作。我可以将东西注入任何其他页面,但显然不能注入此类。有几个人只是说将它注入构造函数,但这对我没有多大帮助,因为我对此很陌生,而且我无法让我发现的例子起作用。不过,这可能是解决方案,也许我只需要以一种可行的方式来做。也可能有更好的方法来创建一个全局类。

【问题讨论】:

【参考方案1】:

根据我从您的问题中推测的内容 - 您希望访问 Blazor Server 中的 HttpContext。如果是这样,那么这段代码 - 归功于 Robin Sue - 为您获取上下文:

            // Server Side Blazor doesn't register HttpClient by default
            // Thanks to Robin Sue - Suchiman https://github.com/Suchiman/BlazorDualMode
            if (!services.Any(x => x.ServiceType == typeof(HttpClient)))
            
                // Setup HttpClient for server side in a client side compatible fashion
                services.AddScoped<HttpClient>(s =>
                
                    // Creating the URI helper needs to wait until the JS Runtime is initialized, so defer it.
                    var uriHelper = s.GetRequiredService<NavigationManager>();
                    return new HttpClient
                    
                        BaseAddress = new Uri(uriHelper.BaseUri)
                    ;
                );
            

如果不是,则忽略答案!

【讨论】:

【参考方案2】:

事实证明,我无法访问通过构造函数注入的任何内容,因此我进行了一些研究,并根据此网站: https://blazor-university.com/dependency-injection/injecting-dependencies-into-blazor-components/

在创建 Blazor 组件实例之后和执行 OnInitialized 或 OnInitializedAsync 生命周期事件之前注入依赖项。这意味着我们不能覆盖组件的构造函数并从那里使用这些依赖项,但我们可以在 OnInitialized* 方法中使用它们。

所以基本上我不能在我的构造函数中使用注入的依赖项。那我得想办法做到这一点!如果我不放弃并继续前进,当我找到另一种方法时,我会更新此内容。

编辑: 我最终使用了一个(imo)不是很好的工作,我在 Global.cs 中创建了一个方法,将用户名字符串设置为放入其中的任何内容。然后我利用了我的共享布局始终被使用的事实,并且可以通过使用&lt;AuthorizeView&gt; 访问用户名,所以我只是使用我在其中一个布局中创建的方法设置用户名,如下所示:

<AuthorizeView>
    <Authorized>
        @
              Global.SetUserName(context.User.Identity.Name);
         
    </Authorized>
</AuthorizeView>

是的,不理想,但它有效,现在这是我的目标。

【讨论】:

以上是关于注入单例依赖项时,HttpContext 为空的主要内容,如果未能解决你的问题,请参考以下文章

使用 kotlin + quarkus 注入一些依赖项时出错

在 Mockito Junit 中 @InjectMocks 后为空

使用依赖注入作为单例的替代方案

Net Core依赖注入

NSManagedObjectContext 的单例?死板的?依赖注入?

依赖注入作用域为瞬态,然后瞬态为单例