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

Web API中含接口属性的Model提交后未进入Controller返回400错误问题

问题引发原因

ASP.NET Core 默认的模型绑定器在反序列化客户端提交的JSON数据时,无法直接实例化接口或者抽象类类型的对象。你定义的CreateNewOrganizationModel里三个属性分别是IOrganizationDetailDto、IList<IUserRoleDetailDto>、IPersonalDetailDto接口类型,反序列化时系统不知道要创建哪个实现类的实例,所以抛出了报错里的"Type is an interface or abstract class and cannot be instantiated"异常,最终返回400 Bad Request错误。

解决方案

这里提供3种常用的可行方案,你可以根据自己的项目情况选择:

  • 方案1:将Model里的接口类型替换为对应的实现类(最常用、最简单)
    直接把属性声明为你写的对应接口实现类即可,比如你有OrganizationDetailDto实现了IOrganizationDetailDto,就修改Model如下:
public class CreateNewOrganizationModel : ICreateNewRegistrationDto
{
    [Required(ErrorMessage = "The {0} is required.")]
    public OrganizationDetailDto OrganizationDetail { get; set; }

    [Required(ErrorMessage = "The {0} is required.")]
    public IList<UserRoleDetailDto> UserRoleDetails { get; set; }

    [Required(ErrorMessage = "The {0} is required.")]
    public PersonalDetailDto PersonalDetail { get; set; }
}
  • 方案2:自定义JSON反序列化转换器,指定接口对应的实现类
    如果你必须保留属性的接口类型声明,可以给接口加JsonConverter特性,或者全局配置反序列化规则,告诉序列化器遇到该接口时用哪个实现类实例化,以System.Text.Json为例:
    首先创建通用的接口转换器:
public class InterfaceConverter<TInterface, TImplementation> : JsonConverter<TInterface> 
    where TImplementation : class, TInterface, new()
{
    public override TInterface Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        return JsonSerializer.Deserialize<TImplementation>(ref reader, options);
    }

    public override void Write(Utf8JsonWriter writer, TInterface value, JsonSerializerOptions options)
    {
        JsonSerializer.Serialize(writer, value, value.GetType(), options);
    }
}

然后在Program.cs里注册转换器:

builder.Services.AddControllers()
    .AddJsonOptions(options =>
    {
        options.JsonSerializerOptions.Converters.Add(new InterfaceConverter<IOrganizationDetailDto, OrganizationDetailDto>());
        options.JsonSerializerOptions.Converters.Add(new InterfaceConverter<IPersonalDetailDto, PersonalDetailDto>());
        options.JsonSerializerOptions.Converters.Add(new InterfaceConverter<IUserRoleDetailDto, UserRoleDetailDto>());
    });
  • 方案3:使用Newtonsoft.Json替换默认的System.Text.Json,并配置类型名处理
    如果项目中用Newtonsoft.Json,你可以配置序列化时携带类型名,反序列化时根据类型名自动实例化对应的实现类,不过这个方案需要客户端提交JSON时也携带$type字段,耦合度较高,不推荐对外公开的API使用。

内容的提问来源于stack exchange,提问作者mnu-nasir

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 06:06:04