我正在尝试使用Jason Taylor's Clean Architecture Template,此模板使用NSwag自动创建TypeScript客户端(角度),但是我不需要创建TS客户端,因此我的主要目标是将其替换为Razor Pages。我已经能够做到这一点,但是CurrentUserService实例化时遇到麻烦,应该在此行中设置UserId:
UserId = httpContextAccessor.HttpContext?.User?.FindFirstValue(ClaimTypes.NameIdentifier);
这是完整的CurrentUserService:
using CleanREC0.Application.Common.Interfaces;
using Microsoft.AspNetCore.Http;
using System.Security.Claims;
namespace CleanREC0.WebUI.Services
{
public class CurrentUserService : ICurrentUserService
{
public CurrentUserService(IHttpContextAccessor httpContextAccessor)
{
UserId = httpContextAccessor.HttpContext?.User?.FindFirstValue(ClaimTypes.NameIdentifier);
}
public string UserId { get; }
}
}
第一次使用HttpContext都是null,这很好,因为一切都已初始化,但是随后的调用总是在所有[[httpContextAccessor.HttpContext.User.Identity属性上返回null,用户显示Identity正常,但即使用户正确登录,其所有属性和声明均为null或未获得任何结果。
以下是我对模板所做的操作的列表:public class Startup
{
public Startup(IConfiguration configuration, IWebHostEnvironment environment)
{
Configuration = configuration;
Environment = environment;
}
public IConfiguration Configuration { get; }
public IWebHostEnvironment Environment { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddApplication();
services.AddInfrastructure(Configuration, Environment);
services.AddScoped<ICurrentUserService, CurrentUserService>();
services.AddHttpContextAccessor();
services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>(); //I have added this line on as suggested on other post, but made no difference.
services.AddHealthChecks()
.AddDbContextCheck<ApplicationDbContext>();
services.AddRazorPages()
.AddFluentValidation(fv => fv.RegisterValidatorsFromAssemblyContaining<IApplicationDbContext>());
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseCustomExceptionHandler();
app.UseHealthChecks("/health");
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
});
}
}
这是从
ConfigureServices调用的
AddApplication
:public static IServiceCollection AddApplication(this IServiceCollection services)
{
services.AddAutoMapper(Assembly.GetExecutingAssembly());
services.AddMediatR(Assembly.GetExecutingAssembly());
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(RequestPerformanceBehaviour<,>));
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(RequestValidationBehavior<,>));
return services;
}
还有AddInfrastructure也在那里被称为:
public static IServiceCollection AddInfrastructure(this IServiceCollection services, IConfiguration configuration, IWebHostEnvironment environment)
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
configuration.GetConnectionString("DefaultConnection"),
b => b.MigrationsAssembly(typeof(ApplicationDbContext).Assembly.FullName)));
services.AddScoped<IApplicationDbContext>(provider => provider.GetService<ApplicationDbContext>());
services.AddDefaultIdentity<ApplicationUser>()
.AddEntityFrameworkStores<ApplicationDbContext>();
if (environment.IsEnvironment("Test"))
{
}
else
{
services.AddTransient<IDateTime, DateTimeService>();
services.AddTransient<IIdentityService, IdentityService>();
services.AddTransient<ICsvFileBuilder, CsvFileBuilder>();
}
services.AddAuthentication();
return services;
}
其他一切似乎都正常。在Razor Page
级别,
User
变量及其Identity包含所有预期的信息和声明。我确定我缺少什么,有人可以指出正确的方向吗?在ASP.NET MVC框架下,HttpContext(因此控制器类为时未设置HttpContext.Session)如您所料,它被构造,但是后来它被设置(“注入”)ControllerBuilder类。
我正在使用的模板随附的CurrentUserService类尝试读取构造函数中的用户声明,因此我将代码移至该属性的getter,该方法执行到该属性实际被使用时为止。那么所有的声明和属性都会被填充。
我的新CurrentUserService看起来像这样:
using CleanREC0.Application.Common.Interfaces; using Microsoft.AspNetCore.Http; using System.Security.Claims; namespace CleanREC0.WebUI.Services { public class CurrentUserService : ICurrentUserService { private IHttpContextAccessor _httpContextAccessor; public CurrentUserService(IHttpContextAccessor httpContextAccessor) { _httpContextAccessor = httpContextAccessor; } public string UserId { get { return _httpContextAccessor.HttpContext?.User?.FindFirstValue(ClaimTypes.NameIdentifier); }} } }