.NET Framework迁移至.NET 8后配置读取空引用异常求助
.NET Framework迁移至.NET 8后空引用异常排查与解决
问题背景
将.NET Framework应用迁移至.NET 8,微软迁移工具执行无报错,但本地运行触发空引用异常,异常发生在Program.cs读取App.config配置项的代码处,具体是System.Configuration.ConfigurationManager.AppSettings获取配置值返回null,导致赋值给config对象属性时引发异常。
相关代码与配置
Program.cs代码片段
using System; using System.Collections.Generic; namespace GenericEmail { class Program { static void Main(string[] args) { if (args.Length > 0) { ConfigSettings config = new ConfigSettings(); // 从参数获取值 config.reportType = args[0]; bool isAdminReport = false; bool isTest = true; if (args.Length > 1) { isAdminReport = Convert.ToBoolean(args[1]); } if (args.Length > 2) { isTest = Convert.ToBoolean(args[2]); } config.isAdminReport = isAdminReport; config.isTest = isTest; // 从配置文件读取值 - 异常触发处 config.emailSubject = System.Configuration.ConfigurationManager.AppSettings["EmailSubject-" + config.reportType]; config.adminEmailAddresses = System.Configuration.ConfigurationManager.AppSettings["Admin-" + config.reportType]; config.noErrorMessage = System.Configuration.ConfigurationManager.AppSettings["NoError-" + config.reportType]; } } } }
App.config配置文件
<?xml version="1.0" encoding="utf-8"?> <configuration> <configSections> <!-- For more information on Entity Framework configuration --> <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=mytoken" requirePermission="false"/> </configSections> <startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8"/> </startup> <appSettings> <add key="TestEmailAddress" value="me@email.com"/> <add key="EmailServer" value="smtp.myserver"/> <add key="EnableSSL" value="false"/> <add key="Port" value="25"/> <add key="EmailSubject-Validation" value="Account # Errors and Unreconciled Jobs"/> <add key="Admin-Validation" value="1@email.com; 2@email.com; 3@email.com; 4@email.com"/> <add key="NoError-Validation" value="There are no validation errors to report at this time."/> <add key="EmailSubject-Blackout" value="Important: AESOP time entered on blackout date"/> <add key="Admin-Blackout" value="me@email.com; x@email.com"/> <add key="NoError-Blackout" value="There are no absences on blackout dates to report at this time."/> <add key="EmailSubject-FFCRA" value="Authorization required for your absence entry"/> <add key="Admin-FFCRA" value="me@email.com; x@email.com"/> <add key="NoError-FFCRA" value="There are no FFCRA absences to report at this time."/> <add key="Sender-FFCRA" value=" y@email.com"/> <add key="EmailSubject-FFCRAReport" value="AESOP FFCRA Absence Report"/> <add key="Admin-FFCRAReport" value="me@email.com; y@email.com"/> <add key="NoError-FFCRAReport" value="There are no FFCRA absences to report at this time."/> <add key="ClientSettingsProvider.ServiceUri" value=""/> </appSettings> <connectionStrings> <add name="mu_report_dataEntities" connectionString="metadata=res://*/mu_report_data.csdl|res://*/mu_report_data.ssdl|res://*/mu_report_data.msl;provider=System.Data.SqlClient;provider connection string="data source=myserver;initial catalog=mytable;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework"" providerName="System.Data.EntityClient"/> </connectionStrings> <entityFramework> <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework"> <parameters> <parameter value="mssqllocaldb"/> </parameters> </defaultConnectionFactory> <providers> <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer"/> </providers> </entityFramework> <system.web> <membership defaultProvider="ClientAuthenticationMembershipProvider"> <providers> <add name="ClientAuthenticationMembershipProvider" type="System.Web.ClientServices.Providers.ClientFormsAuthenticationMembershipProvider, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=mytoken" serviceUri=""/> </providers> </membership> <roleManager defaultProvider="ClientRoleProvider" enabled="true"> <providers> <add name="ClientRoleProvider" type="System.Web.ClientServices.Providers.ClientRoleProvider, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=mytoken" serviceUri="" cacheTimeout="86400"/> </providers> </roleManager> </system.web> </configuration>
解决步骤
1. 安装ConfigurationManager NuGet包
.NET 8不再默认包含System.Configuration.ConfigurationManager组件,需手动安装:
Install-Package System.Configuration.ConfigurationManager
2. 修正配置文件属性与内容
- 右键App.config文件→属性,将复制到输出目录设置为「始终复制」,确保配置文件能被程序读取到。
- 修改
startup节点,移除.NET Framework相关配置,替换为.NET 8的支持:
<startup> <supportedRuntime version="v8.0" /> </startup>
3. 验证配置键名匹配
检查传入的args[0]值(即config.reportType)是否与App.config中的键名后缀完全一致(区分大小写)。比如传入"validation"(小写)会匹配不到"EmailSubject-Validation"(大写V),导致返回null。可添加调试输出确认实际拼接后的键名:
var subjectKey = "EmailSubject-" + config.reportType; Console.WriteLine("Attempting to read key: " + subjectKey); config.emailSubject = ConfigurationManager.AppSettings[subjectKey];
4. (推荐)改用.NET 8原生配置系统
若要适配.NET 8最佳实践,建议切换到Microsoft.Extensions.Configuration:
- 安装必要NuGet包:
Install-Package Microsoft.Extensions.Configuration.Json Install-Package Microsoft.Extensions.Configuration.FileExtensions
- 创建
appsettings.json文件,将App.config的appSettings转换为JSON格式:
{ "TestEmailAddress": "me@email.com", "EmailServer": "smtp.myserver", "EnableSSL": "false", "Port": "25", "EmailSubject-Validation": "Account # Errors and Unreconciled Jobs", "Admin-Validation": "1@email.com; 2@email.com; 3@email.com; 4@email.com", "NoError-Validation": "There are no validation errors to report at this time.", // 其他配置项... }
- 修改Program.cs的配置读取逻辑:
using Microsoft.Extensions.Configuration; using System.IO; // 构建配置对象 var configBuilder = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("appsettings.json", optional: false); IConfiguration configuration = configBuilder.Build(); // 读取配置 config.emailSubject = configuration["EmailSubject-" + config.reportType]; config.adminEmailAddresses = configuration["Admin-" + config.reportType]; config.noErrorMessage = configuration["NoError-" + config.reportType];
5. 检查ConfigSettings类定义
确保ConfigSettings类的对应属性为可赋值状态(如public字段或带setter的属性),避免因属性只读导致赋值异常。
内容的提问来源于stack exchange,提问作者Kimber Warden
相关产品推荐
相关产品推荐

