.NET 5升级.NET 7部署Ubuntu后connectionString为空异常求助
.NET 7部署到Ubuntu后无法读取appsettings.json中的连接字符串
我已将API从.NET 5升级至.NET 7并部署到Ubuntu 23.04服务器,本地环境下API与数据库连接正常且可处理请求,但部署到服务器后,程序无法读取appsettings.json中的connectionString,启动时抛出异常:
Unhandled exception. System.ArgumentNullException: Value cannot be null. (Parameter 'connectionString')
相关配置与代码
appsettings.json
{ "AppSettings": { "Secret": "*************", "EmailFrom": "********", "SmtpHost": "v******", "SmtpPort": 587, "SmtpUser": "a*****", "SmtpPass": "HJu******" }, "ConnectionStrings": { "WebApiDatabase": "Data Source=WebApiDatabase.db", "HangfireConnection": "Server=**.**.***.***;Port=5432;Database=Min;User Id=postgres;Password=min***;" //server //"HangfireConnection": "Host=localhost;Port=5432;Database=Min;User Id=postgres;Password=*****;" // local }, "Logging": { "LogLevel": { "Default": "Information", "Microsoft": "Warning", "Microsoft.Hosting.Lifetime": "Information", "Hangfire": "Information" } }, "AllowedHosts": "*", "postgresqlconnection": { "connectionString": "Server=**.**.***.***;Port=5432;Database=Min;User Id=postgres;Password=min***;" //server //"connectionString": "Host=localhost;Port=5432;Database=Min;User Id=postgres;Password=*****;" // local }, "mongoconnection": { "connectionString": "mongodb://localhost:27017/?readPreference=primary&appname=MongoDB%20Compass%20Community&ssl=false", "database": "backlog", "collection": "rawData", "collectionpMedian": "resultPmedian", "collectionClustering": "resultClustering" }, "urlSettings": { "staticPageUrl": "http://**.**.***.***", "backendUrl": "http://**.**.***.***" }, "variousSettings": { "defaultMessage": "A default message if nothing is found in the database." } }
Startup.cs
services.AddHangfire(configuration => configuration .SetDataCompatibilityLevel(CompatibilityLevel.Version_170) .UseSimpleAssemblyNameTypeSerializer() .UseRecommendedSerializerSettings() .UsePostgreSqlStorage(Configuration.GetConnectionString("HangfireConnection")));
DataContext.cs
private readonly IConfiguration Configuration; public DataContext(IConfiguration configuration) { Configuration = configuration; } protected override void OnConfiguring(DbContextOptionsBuilder options) { // connect to postgress database var connectionString = Configuration["postgresqlconnection:connectionString"]; options.UseNpgsql(connectionString); }
完整错误日志
root@ubuntu-4gb:/# /usr/bin/dotnet /var/www/MinAPI/MinWebApi.dll Unhandled exception. System.ArgumentNullException: Value cannot be null. (Parameter 'connectionString') at Hangfire.PostgreSql.PostgreSqlStorage..ctor(String connectionString, Action`1 connectionSetup, PostgreSqlStorageOptions options) at Hangfire.PostgreSql.PostgreSqlBootstrapperConfigurationExtensions.UsePostgreSqlStorage(IGlobalConfiguration configuration, String connectionString, Action`1 connectionSetup, PostgreSqlStorageOptions options) at Hangfire.PostgreSql.PostgreSqlBootstrapperConfigurationExtensions.UsePostgreSqlStorage(IGlobalConfiguration configuration, String connectionString) at WebApi.Startup.<ConfigureServices>b__4_2(IGlobalConfiguration configuration) in D:\C Sharp\Startup.cs:line 46 at Hangfire.HangfireServiceCollectionExtensions.<>c__DisplayClass0_0.<AddHangfire>b__0(IServiceProvider provider, IGlobalConfiguration config) at Hangfire.HangfireServiceCollectionExtensions.<>c__DisplayClass1_0.<AddHangfire>b__14(IServiceProvider serviceProvider) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitFactory(FactoryCallSite factoryCallSite, RuntimeResolverContext context) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitRootCache(ServiceCallSite callSite, 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.ServiceProvider.CreateServiceAccessor(Type serviceType) at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory) at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope) at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetService[T](IServiceProvider provider) at Hangfire.HangfireServiceCollectionExtensions.ThrowIfNotConfigured(IServiceProvider serviceProvider) at Hangfire.HangfireServiceCollectionExtensions.CreateBackgroundJobServerHostedService(IServiceProvider provider, JobStorage storage, IEnumerable`1 additionalProcesses, BackgroundJobServerOptions options) at Hangfire.HangfireServiceCollectionExtensions.<>c__DisplayClass9_0.<AddHangfireServerInner>b__0(IServiceProvider provider) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitFactory(FactoryCallSite factoryCallSite, RuntimeResolverContext context) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitDisposeCache(ServiceCallSite transientCallSite, RuntimeResolverContext context) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitIEnumerable(IEnumerableCallSite enumerableCallSite, RuntimeResolverContext context) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitNoCache(ServiceCallSite callSite, TArgument argument) 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__DisplayClass2_0.<RealizeService>b__0(ServiceProviderEngineScope scope) at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope) at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType) at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider) at Microsoft.Extensions.Hosting.Internal.Host.StartAsync(CancellationToken cancellationToken) at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.RunAsync(IHost host, CancellationToken token) at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.RunAsync(IHost host, CancellationToken token) at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.Run(IHost host) at WebApi.Program.Main(String[] args) in D:\C Sharp\Program.cs:line 12
已尝试的解决方法
- 硬编码连接字符串
- 修改变量名
- 同步appsettings.Development.json
仅同步配置后短暂正常,但重启服务后异常复现。
解决方案
1. 检查appsettings.json的部署状态
- 确认服务器
/var/www/MinAPI/目录下存在正确的appsettings.json,内容与本地测试版本一致(重点核对HangfireConnection和postgresqlconnection节点)。 - 修复文件权限,确保dotnet进程可读取:
sudo chmod 644 /var/www/MinAPI/appsettings.json sudo chown www-data:www-data /var/www/MinAPI/appsettings.json
2. 验证环境配置加载逻辑
.NET在Linux环境下优先加载环境特定配置文件(如appsettings.Production.json),若该文件存在且未配置对应连接字符串,会覆盖默认配置:
- 检查服务器是否存在
appsettings.Production.json,若存在则补充完整的ConnectionStrings和postgresqlconnection节点。 - 启动时显式指定环境:
或设置环境变量:dotnet /var/www/MinAPI/MinWebApi.dll --environment Productionexport ASPNETCORE_ENVIRONMENT=Production dotnet /var/www/MinAPI/MinWebApi.dll
3. 修复配置读取方式
- 对DataContext的配置读取添加空值检查,改用更可靠的Section读取:
var connectionString = Configuration.GetSection("postgresqlconnection").GetValue<string>("connectionString"); if(string.IsNullOrEmpty(connectionString)) { throw new InvalidOperationException("PostgreSQL connection string is not configured."); } options.UseNpgsql(connectionString); - 对Hangfire配置同样添加空值验证:
var hangfireConn = Configuration.GetConnectionString("HangfireConnection"); if(string.IsNullOrEmpty(hangfireConn)) { throw new InvalidOperationException("Hangfire connection string is not configured."); } services.AddHangfire(configuration => configuration .SetDataCompatibilityLevel(CompatibilityLevel.Version_170) .UseSimpleAssemblyNameTypeSerializer() .UseRecommendedSerializerSettings() .UsePostgreSqlStorage(hangfireConn));
4. 检查发布模式与文件包含
- 在Visual Studio中右键appsettings.json,设置属性→复制到输出目录→选择“始终复制”,确保发布时文件被包含到输出目录。
- 确认发布后的
bin/Release/net7.0/publish/目录中存在appsettings.json,再将该目录完整部署到服务器。
5. 排查环境变量覆盖问题
.NET配置加载顺序为:环境变量→命令行参数→环境特定配置文件→默认配置文件,若服务器存在同名环境变量会覆盖连接字符串:
- 检查环境变量:
printenv | grep ConnectionStrings - 若存在相关变量,临时取消设置:
unset ConnectionStrings__HangfireConnection
内容的提问来源于stack exchange,提问作者Bashar Al-shaibani
相关产品推荐
相关产品推荐

