c# - 带有 EF Core 迁移和 IHttpContextAccessor 的 ASP.NET Core (3.1)
问题描述
我正在尝试为我的 ASP.NET Core API 项目添加 EF Core 迁移。不幸的是,迁移必须处理添加迁移的一些麻烦,因为我正在将一个注入IHttpContextAccessor
到我的一个提供程序中。
我正在打电话services.AddHttpContextAccessor();
,services.AddDbContext<SCContext>(builder => builder.UseSqlServer(connectionstring));
在我的 startup.cs 中。
如果我正在运行 >dotnet run
并执行一些请求,一切正常。
但是,如果我尝试运行>dotnet ef migrations add InitialCreate
以下日志(两个命令都在 api 项目目录路径中执行):
Build started...
Build succeeded.
System.NullReferenceException: Object reference not set to an instance of an object.
at SocietyCloud.Services.Provider.CredentialsProvider..ctor(IHttpContextAccessor httpContextAccessor) in E:\Bibliotheken\Projects\societycloud\Application\SocietyCloud.Services\Provider\CredentialsProvider.cs:line 15
at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor, Boolean wrapExceptions)
at System.Reflection.RuntimeConstructorInfo.Invoke(BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite singletonCallSite, RuntimeResolverContext context)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite singletonCallSite, RuntimeResolverContext context)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Resolve(ServiceCallSite callSite, ServiceProviderEngineScope scope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.DynamicServiceProviderEngine.<>c__DisplayClass1_0.<RealizeService>b__0(ServiceProviderEngineScope scope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType)
at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.GetServiceOrCreateInstance(IServiceProvider provider, Type type)
at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.<>c__DisplayClass13_2.<FindContextTypes>b__11()
at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.CreateContext(Func`1 factory)
at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.CreateContext(String contextType)
at Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.AddMigration(String name, String outputDir, String contextType)
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigrationImpl(String name, String outputDir, String contextType)
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigration.<>c__DisplayClass0_0.<.ctor>b__0()
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.<>c__DisplayClass3_0`1.<Execute>b__0()
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)
Object reference not set to an instance of an object.
有没有人遇到同样的问题?
启动.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddDefaultPolicy(builder =>
builder.SetIsOriginAllowed(_ => true)
.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader());
});
services.AddControllers();
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "TEST", Version = "v1" });
});
AutoMapperConfig.Configure(services);
OptionsConfig.Configure(services, Configuration);
AuthenticationConfig.Configure(services, Configuration);
DependencyConfig.Configure(services, Configuration);
}
依赖配置.cs
public static void Configure(IServiceCollection services, IConfiguration configuration)
{
// Register provider
services.AddHttpContextAccessor();
var openibanurl = configuration[$"{nameof(ExternalApisOptions)}:{nameof(ExternalApisOptions.OpenIbanUrl)}"];
services.AddHttpClient<IOpenIbanProvider, OpenIbanProvider>(configure => configure.BaseAddress = new Uri(openibanurl));
// Register DBContext
var connectionstring = configuration[$"{nameof(AzureOptions)}:{nameof(AzureOptions.SqlConnectionstring)}"];
services.AddDbContext<SCContext>(builder => builder.UseSqlServer(connectionstring));
// Register services
foreach (var (Contract, Implementation) in typeof(MembershipsService).Assembly.GetTypesWithImplementations<IService>())
services.AddScoped(Contract, Implementation);
// Register validator
services.AddScoped<IViewModelValidator<VMAddMembership>, VMAddMembershipValidator>();
}
CredentialsProvider.cs
public class CredentialsProvider : ICredentialsProvider
{
public Guid? AccountId { get; private set; }
public Guid? SocietyId { get; private set; }
public CredentialsProvider(IHttpContextAccessor httpContextAccessor)
{
if (httpContextAccessor.HttpContext.User.Identity.IsAuthenticated)
{
AccountId = GetGuid(httpContextAccessor.HttpContext, SCClaims.AccountId);
SocietyId = GetGuid(httpContextAccessor.HttpContext, SCClaims.SocietyId);
}
}
private Guid? GetGuid(HttpContext context, SCClaims claim)
{
if (Guid.TryParse(context.User.Claims?.FirstOrDefault(x => x.Type == Enum.GetName(typeof(SCClaims), claim))?.Value, out var societyid))
return societyid;
return null;
}
}
解决方案
HttpContext
在 的构造函数中访问CredentialsProvider
将失败,因为在可以填充上下文及其成员之前,您将在生命周期中过早访问它
public class CredentialsProvider : ICredentialsProvider {
private readonly IHttpContextAccessor httpContextAccessor;
public CredentialsProvider(IHttpContextAccessor httpContextAccessor) {
this.httpContextAccessor = httpContextAccessor;
}
public Guid? AccountId => GetGuid(SCClaims.AccountId);
public Guid? SocietyId => GetGuid(SCClaims.SocietyId);
private Guid? GetGuid(SCClaims claim) {
if (Guid.TryParse(httpContextAccessor.HttpContext.User?.Claims?
.FirstOrDefault(x => x.Type == Enum.GetName(typeof(SCClaims), claim))?.Value,
out var societyid)
)
return societyid;
return null;
}
}
尽量避免在构造函数中做太多的逻辑。它们主要用于分配初始值。
推荐阅读
- java - Maven结构内的验收测试?
- python - sublimetext 3 按回车键禁用自动完成
- adaptive-cards - Teams 和 PVA 自适应卡与 1.4 的兼容性
- vue.js - v-tour 中的动态偏移
- php - 无法通过本地主机访问 xampp ubuntu 中的 php 文件
- mediawiki - MediaWiki API 从文章的另见部分获取所有链接
- python - 蟒蛇硒。下载后如何切换回上一个窗口/标签打开一个新标签
- python - 尝试拟合我的模型时出现“ValueError:形状 (64, 4) 和 (64, 10) 不兼容”
- github - 如何不将“.env”文件推送到 Github 存储库?
- python - 我对 django-mptt 有问题。我是第一次使用 django-mptt,但出现以下错误