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

ASP.NET Core Web API基类参数无法获取派生通知属性问题

解决方案

不需要为每种通知类型单独编写控制器。问题根源是ASP.NET Core默认的JSON反序列化逻辑只会按照参数声明的基类类型解析数据,无法自动识别传入数据对应的派生类,只要配置好多态反序列化规则,就能自动识别通知类型、解析全部属性。


方案1:使用System.Text.Json内置多态反序列化(推荐,适用于.NET 7+版本)

ASP.NET Core默认使用System.Text.Json处理JSON序列化/反序列化,.NET 7开始原生支持多态反序列化配置,只需要给基类添加特性标注即可:

  • 第一步:给NotificationSuper基类添加多态配置特性,指定你已经定义的Type字段作为类型判别依据,同时注册所有派生类和对应的判别值:
using System.Text.Json.Serialization;

// 指定用JSON中的Type字段作为类型判断依据
[JsonPolymorphic(TypeDiscriminatorPropertyName = nameof(NotificationSuper.Type))]
// 注册所有通知类型,第二个参数为和Type字段值对应的标识,和Flutter端约定一致即可
[JsonDerivedType(typeof(NotificationSuper), "base")]
[JsonDerivedType(typeof(UnitNotification), "unit")]
[JsonDerivedType(typeof(MaintenanceNotification), "maintenance")]
public class NotificationSuper 
{
    public string  Title { get; set; }
    public string Body { get; set; }
    public string Token { get; set; }
    public string Type { get; set; }
}
  • 第二步:Flutter端传参时,必须给Type字段传和后端约定好的对应值,比如发送维修类通知时Type字段传"maintenance",发送单元类通知时传"unit"。
  • 控制器代码完全不需要修改,接口接收到请求后会自动把JSON反序列化为对应派生类的实例,所有派生类的独有属性都会被正确填充。后续业务逻辑中可以通过模式匹配识别具体类型做对应处理:
bool success = notification switch
{
    MaintenanceNotification maintenanceNotify => await Notify.SendMaintenanceNotify(maintenanceNotify),
    UnitNotification unitNotify => await Notify.SendUnitNotify(unitNotify),
    _ => await Notify.SendCommonNotify(notification)
};
  • 后续新增通知类型时,只需要新建继承自对应基类的通知类,再在NotificationSuper的JsonDerivedType特性中追加一行类型注册即可,不需要修改控制器、不需要新增接口。

方案2:自定义JSON转换器(适用于.NET 6及更低版本)

如果项目使用.NET 6及更早版本,没有内置多态反序列化特性,可以自定义JSON转换器实现同样的逻辑:

  • 第一步:编写自定义转换器,逻辑是先读取JSON中的Type字段值,根据约定的映射关系找到对应的目标类型,再执行反序列化:
public class NotificationConverter : JsonConverter<NotificationSuper>
{
    public override NotificationSuper Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        using var doc = JsonDocument.ParseValue(ref reader);
        var root = doc.RootElement;
        // 读取Type字段值
        var type = root.GetProperty("Type").GetString();
        
        return type switch
        {
            "maintenance" => root.Deserialize<MaintenanceNotification>(options),
            "unit" => root.Deserialize<UnitNotification>(options),
            _ => root.Deserialize<NotificationSuper>(options)
        };
    }

    public override void Write(Utf8JsonWriter writer, NotificationSuper value, JsonSerializerOptions options)
    {
        JsonSerializer.Serialize(writer, value, value.GetType(), options);
    }
}
  • 第二步:把转换器注册到全局JSON配置中,在Program.cs里添加配置:
builder.Services.AddControllers()
    .AddJsonOptions(options =>
    {
        options.JsonSerializerOptions.Converters.Add(new NotificationConverter());
    });

该方案效果和方案1完全一致,后续新增通知类型只要在转换器的switch分支中添加对应映射即可。


注意事项

  • 不推荐使用Newtonsoft.Json的TypeNameHandling配置实现自动多态反序列化,该配置存在远程代码执行安全风险。
  • 前后端必须严格约定Type字段的传值规则,传值和后端映射不匹配时会导致反序列化失败。

内容的提问来源于stack exchange,提问作者Abanoub Refaat

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 22:36:19