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

ASP.NET Core 2.0返回IActionResult时控制SerializerSettings的问题

在ASP.NET Core 2.0中为抽象基类序列化添加具体类型标识

嗨,我来帮你搞定这个问题!在ASP.NET Core 2.0 WebAPI里,要让抽象基类Trade的JSON序列化结果包含具体类型的标识,我们可以通过配置**Newtonsoft.Json(Json.NET)**的序列化规则来实现——毕竟ASP.NET Core 2.0默认就是用Json.NET处理JSON序列化的。

下面是具体的实现步骤:

1. 标记抽象基类的子类

首先,你需要告诉Json.NET哪些类型是Trade的具体子类。最直接的方式是在抽象基类上添加[JsonDerivedType]特性:

using Newtonsoft.Json;

[JsonDerivedType(typeof(StockTrade), typeName: "StockTrade")]
[JsonDerivedType(typeof(ForeignExchangeTrade), typeName: "ForeignExchangeTrade")]
public abstract class Trade
{
    public int Id { get; set; }
    // 其他公共属性
}

// 示例具体子类
public class StockTrade : Trade
{
    public string StockSymbol { get; set; }
    public int Quantity { get; set; }
}

public class ForeignExchangeTrade : Trade
{
    public string CurrencyPair { get; set; }
    public decimal Amount { get; set; }
}

这里的typeName参数会作为类型标识出现在最终的JSON里,方便反序列化时识别具体类型。

2. 全局配置Json.NET的序列化设置

接下来,在Startup.cs的ConfigureServices方法中,配置Json.NET开启类型名称处理:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc()
        .AddJsonOptions(options =>
        {
            // 自动为多态类型添加类型标识字段(默认字段名为$type)
            options.SerializerSettings.TypeNameHandling = TypeNameHandling.Auto;
            
            // 可选:自定义类型标识的格式,比如只保留类型名不包含程序集信息
            options.SerializerSettings.TypeNameAssemblyFormatHandling = TypeNameAssemblyFormatHandling.Simple;
        });
}
  • TypeNameHandling.Auto:只会在序列化多态类型(比如抽象基类的实例)时自动添加$type字段,避免不必要的冗余。
  • 如果需要强制所有对象都添加类型标识,可以改用TypeNameHandling.Objects或TypeNameHandling.All。

3. 验证序列化结果

现在当你的Get方法返回具体的Trade子类实例时,序列化后的JSON会包含类型标识,比如:

{
  "$type": "YourApp.Models.StockTrade",
  "Id": 5,
  "StockSymbol": "AAPL",
  "Quantity": 100
}

4. 安全提示(重要)

使用TypeNameHandling时要注意反序列化安全问题——如果你的API接受来自不可信来源的JSON,恶意攻击者可能通过构造特定的$type字段来触发危险类型的反序列化。

为了避免这个风险,建议自定义SerializationBinder来限制允许反序列化的类型:

options.SerializerSettings.SerializationBinder = new TradeTypeBinder();

public class TradeTypeBinder : ISerializationBinder
{
    private readonly HashSet<Type> _allowedTypes = new HashSet<Type>
    {
        typeof(StockTrade),
        typeof(ForeignExchangeTrade)
    };

    public Type BindToType(string assemblyName, string typeName)
    {
        // 查找允许的类型,找不到则抛出异常
        var allowedType = _allowedTypes.FirstOrDefault(t => t.FullName == typeName);
        if (allowedType == null)
        {
            throw new ArgumentException($"不允许反序列化类型:{typeName}");
        }
        return allowedType;
    }

    public void BindToName(Type serializedType, out string assemblyName, out string typeName)
    {
        assemblyName = null; // 不输出程序集名称
        typeName = serializedType.FullName;
    }
}

这样就能确保只有你指定的Trade子类可以被反序列化,提升API的安全性。

内容的提问来源于stack exchange,提问作者David Waterworth

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 09:58:23