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

C# .NET5 REST API OData下多态JSON转换器400输入无效问题求解

解决方案

该问题本质是OData默认使用独立的序列化/反序列化管道,且EDM未显式声明继承层级时,会提前校验请求结构并拦截,导致全局配置的自定义JsonConverter不会被触发,可按以下步骤配置:

1. 显式在EDM模型中声明类继承关系

在构建EDM模型时,除了原有QuizQuestionDto的注册外,需要主动声明QuizOptionDto及其子类的继承关系:

private static IEdmModel GetEdmModel()
{
    var builder = new ODataConventionModelBuilder();
    // 若QuizOptionDto是独立实体则用EntityType,若是依附于其他类的复杂属性则用ComplexType
    builder.ComplexType<QuizOptionDto>();
    // 显式声明派生类的继承关系
    builder.ComplexType<TextOptionDto>().DerivesFrom<QuizOptionDto>();
    builder.ComplexType<ImageOptionDto>().DerivesFrom<QuizOptionDto>();
    // 保留原有的QuizQuestionDto注册
    builder.EntitySet<QuizQuestionDto>("QuizQuestions");
    return builder.GetEdmModel();
}

2. 配置OData使用NewtonsoftJson并继承全局序列化设置

OData默认使用System.Text.Json作为序列化组件,你全局配置的NewtonsoftJson参数不会自动传入OData管道,需要手动配置替换:

services.AddControllers()
    .AddNewtonsoftJson(options =>
    {
        // 原有全局配置
        options.SerializerSettings.TypeNameHandling = TypeNameHandling.All;
        options.SerializerSettings.Converters.Add(new QuizOptionJsonConverter());
    })
    .AddOData(options =>
    {
        // 保留原有OData查询功能配置
        options.Select().Filter().OrderBy().Expand().Count().SetMaxTop(100);
        // 配置OData路由,注入NewtonsoftJson序列化提供器
        options.AddRouteComponents("odata", GetEdmModel(), svc =>
        {
            svc.AddSingleton<IODataSerializerProvider, NewtonsoftJsonODataSerializerProvider>();
            svc.AddSingleton<IODataDeserializerProvider, NewtonsoftJsonODataDeserializerProvider>();
            // 传入和全局一致的序列化配置
            svc.AddSingleton(new ODataNewtonsoftJsonSerializerSettings
            {
                SerializerSettings = new JsonSerializerSettings
                {
                    TypeNameHandling = TypeNameHandling.All,
                    Converters = { new QuizOptionJsonConverter() }
                }
            });
        });
    });

// 可选:若仍存在请求提前被校验拦截的问题,可关闭OData内置模型校验
services.Configure<ODataOptions>(opt =>
{
    opt.ValidateFeature = null;
});

3. 校验自定义JsonConverter的CanConvert逻辑

确保转换器的类型判断逻辑适配OData管道传入的类型:

public override bool CanConvert(Type objectType)
{
    // 支持基类及其所有子类的转换
    return typeof(QuizOptionDto).IsAssignableFrom(objectType);
}

以上配置适配OData 8.x + .NET 5运行环境,配置完成后即可同时保留OData功能和多态反序列化能力。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 23:30:02