我想在我的Blazor应用程序中创建一个全局类,该类包含一个函数,该函数通过我从Windows身份验证中获得的用户用户名来获取用户的部门,但我似乎无法通过全局类访问HttpContextAccessor
。当我注入它时,它的行为就像它可以访问HttpContext
,但当它运行时,我会得到错误
System.NullReferenceException:"对象引用未设置为对象的实例。">
并且当您在局部变量中查看访问器时,它为null。
我在谷歌上搜索了很多,但找不到任何与我正在做的事情以及我目前对这些事情如何运作的了解相结合的东西。
这是我的全球课程:
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");
});
}
}
谷歌说要使用services.AddScoped<Global>
,但我发现这不适用于我的CalculatedDepartment函数,当我使用services.AddSingleton<Global>
时,它有效,所以我保持这种方式。
它似乎对我试图以这种方式注入到该文件中的任何内容都是这样做的。我可以把东西注入任何其他页面,但显然不能注入这个类。有一些人只是简单地说要把它注入构造函数,但这对我没有多大帮助,因为我对这方面还很陌生,我找不到合适的例子。这可能是解决方案,也许我只需要以一种可行的方式来做。也许还有一种更好的方式来打造一个全球性的课堂。
根据我从您的问题中推测的内容-您希望访问Blazor服务器中的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)
};
});
}
如果没有,那么忽略答案!
事实证明,我无法访问通过构造函数注入的任何内容,所以我做了一些研究,并根据本网站:https://blazor-university.com/dependency-injection/injecting-dependencies-into-blazor-components/
依赖项是在创建Blazor组件实例之后以及执行OnInitialized或OnInitializedSync生命周期事件之前注入的。这意味着我们不能重写组件的构造函数并从那里使用这些依赖项,但我们可以在OnInitialized*方法中使用它们。
所以基本上我不能在构造函数中使用注入的依赖项。那我得另辟蹊径了!如果我不放弃并继续前进,我会在找到另一种方法时更新它。
编辑:我最终使用了一个(imo(不太好的方法,我在Global.cs中创建了一个方法,将用户名字符串设置为其中的任何内容。然后我使用了这样一个事实,即我的共享布局一直在使用,并且可以通过使用<AuthorizeView>
访问用户名,所以我只使用我在其中一个布局中创建的方法设置用户名,如下所示:
<AuthorizeView>
<Authorized>
@{
Global.SetUserName(context.User.Identity.Name);
}
</Authorized>
</AuthorizeView>
所以,是的,不理想,但它是有效的,现在这是我的目标。