You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.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 Production
    
    或设置环境变量:
    export 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 00:08:11