.NET 5控制器返回含子类属性的基类列表方法咨询
问题:.NET 5控制器返回基类对象列表时如何保留子类属性?
在.NET 5控制器中返回包含子类属性的基类对象列表时,JSON结果中无法看到派生类属性,但将List<StepBaseDto>改为List<object>或dynamic可正常显示。现有代码定义如下:
基类与派生类Dto:
public class StepBaseDto { public string Title { get; set; } public int Order { get; set; } public StepType StepType { get; set; } public bool IsDone { get; set; } public string Description { get; set; } public string PropertyLabel { get; protected set; } public Guid ProtocolId { get; set; } public List<SubStepDto> SubSteps { get; set; } } public class StartDateStepDto : StepBaseDto { public DateTime? StartingDate { get; set; } } public class ProtocolDto : ProtocolBaseDto { public List<StepBaseDto> StepSequence { get; set; } }
端点定义:
public override Task<ProtocolDto> GetAsync(Guid id)
基于ABP框架5.3.4和Automapper,希望找到无需替换基类为object或dynamic的解决方案。
解决方案
1. 配置System.Text.Json支持多态序列化
.NET 5默认使用System.Text.Json,默认不会序列化基类集合中的派生类属性,需显式配置多态类型信息。
方式一:通过特性标记基类
直接在基类StepBaseDto上添加JsonDerivedType特性,指定所有派生类:
[JsonDerivedType(typeof(StartDateStepDto), typeDiscriminator: "StartDate")] // 如有其他派生类,继续添加[JsonDerivedType]特性 public class StepBaseDto { // 原有属性定义 }
方式二:在服务配置中全局设置
在Startup.cs的ConfigureServices方法中配置Json序列化选项:
services.AddControllers() .AddJsonOptions(options => { options.JsonSerializerOptions.TypeInfoResolver = new DefaultJsonTypeInfoResolver { Modifiers = { typeInfo => { if (typeInfo.Type == typeof(StepBaseDto)) { // 添加所有需要支持的派生类 typeInfo.PolymorphismOptions.AddDerivedType(typeof(StartDateStepDto)); } } } }; });
2. 适配ABP框架的序列化配置
ABP框架5.x有自己的序列化配置体系,需在模块类中配置AbpSystemTextJsonSerializerOptions:
public override void ConfigureServices(ServiceConfigurationContext context) { Configure<AbpSystemTextJsonSerializerOptions>(options => { options.JsonSerializerOptions.TypeInfoResolver = new DefaultJsonTypeInfoResolver { Modifiers = { typeInfo => { if (typeInfo.Type == typeof(StepBaseDto)) { typeInfo.PolymorphismOptions.AddDerivedType(typeof(StartDateStepDto)); } } } }; }); }
3. 确保Automapper映射保留派生类类型
如果映射过程中Automapper将派生类实例转换为基类,会导致序列化丢失属性,需在Automapper配置中添加Include规则:
// 配置实体到Dto的映射 CreateMap<StartDateStep, StartDateStepDto>(); CreateMap<StepBase, StepBaseDto>() .Include<StartDateStep, StartDateStepDto>(); // 关联派生类映射 // 如有其他派生类,重复上述Include配置
这样当映射StepBase集合时,Automapper会根据实际实体类型创建对应的Dto派生类实例,序列化时自然保留子类属性。
内容的提问来源于stack exchange,提问作者Mainumbi
相关产品推荐
相关产品推荐

