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

ASP.NET Web API调用GetPrizes()时序列化失败问题排查求助

问题描述

我正在开发一个包含3个控制器(HomeController、LaureatesController、PrizesController)的ASP.NET Web API项目。调用PrizesController中的GetPrizes() GET方法时,出现以下错误:

The 'ObjectContent`1' type failed to serialize the response body for content type 'application/json; charset=utf-8'

相关代码如下:

PrizesController代码

private ApplicationDbContext db = new ApplicationDbContext();

public IEnumerable<object> GetPrizes()
{
    var prizes = db.Prizes.ToList()
                   .Select(prize => new
                                    {
                                        prize.PrizeID,
                                        prize.Category,
                                        prize.Year,
                                        Laureates = prize.Laureates.Select(Laureate => new
                                        {
                                            Laureate.LaureateID,
                                            Laureate.Surname,
                                            Laureate.FirstName,
                                            Laureate.Gender,
                                            Laureate.Born,
                                            Laureate.BornCountry,
                                            Laureate.Died
                                        })
                                    });
            
    return db.Prizes;
}

WebApiConfig.cs配置

public static void Register(HttpConfiguration config)
{
    // Web API configuration and services

    // Web API routes
    config.MapHttpAttributeRoutes();

    config.Routes.MapHttpRoute(
        name: "DefaultApi",
        routeTemplate: "api/{controller}/{id}",
        defaults: new { id = RouteParameter.Optional }

    );

    var json = config.Formatters.JsonFormatter;
    json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects;
    config.Formatters.Remove(config.Formatters.XmlFormatter);
    json.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;

}

Global.asax代码

public class MvcApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();
        GlobalConfiguration.Configure(WebApiConfig.Register);
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);
    }
}
错误原因分析
  • 返回对象不匹配:方法内构建了处理后的匿名类型集合prizes,但最终返回的是原始实体集合db.Prizes。原始实体存在双向导航属性(Prize与Laureate互相引用),即便配置了ReferenceLoopHandling.Ignore,序列化时仍可能因延迟加载触发的关联加载导致失败。
  • 延迟加载与代理对象问题:EF默认启用延迟加载,返回原始实体时,序列化器会尝试加载关联的Laureates数据,过程中生成的动态代理对象无法被正常序列化。
解决办法

方案1:返回处理后的匿名对象集合

修改GetPrizes()方法,确保返回预先构建好的匿名类型集合,而非原始实体:

public IEnumerable<object> GetPrizes()
{
    var prizes = db.Prizes.ToList()
                   .Select(prize => new
                                    {
                                        prize.PrizeID,
                                        prize.Category,
                                        prize.Year,
                                        Laureates = prize.Laureates.Select(Laureate => new
                                        {
                                            Laureate.LaureateID,
                                            Laureate.Surname,
                                            Laureate.FirstName,
                                            Laureate.Gender,
                                            Laureate.Born,
                                            Laureate.BornCountry,
                                            Laureate.Died
                                        })
                                    });
            
    return prizes; // 返回处理后的集合,替换原db.Prizes
}

方案2:禁用延迟加载与代理创建

若需返回原始实体,可在DbContext中禁用延迟加载和动态代理生成,避免序列化时的关联加载与代理对象问题:

public class ApplicationDbContext : DbContext
{
    public ApplicationDbContext()
    {
        Configuration.LazyLoadingEnabled = false;
        Configuration.ProxyCreationEnabled = false;
    }

    // DbSet定义...
}

方案3:使用DTO类(推荐)

创建专用的DTO(数据传输对象)类,明确控制序列化的数据结构,提升代码可维护性:

// PrizeDTO.cs
public class PrizeDTO
{
    public int PrizeID { get; set; }
    public string Category { get; set; }
    public int Year { get; set; }
    public List<LaureateDTO> Laureates { get; set; }
}

// LaureateDTO.cs
public class LaureateDTO
{
    public int LaureateID { get; set; }
    public string Surname { get; set; }
    public string FirstName { get; set; }
    public string Gender { get; set; }
    public DateTime? Born { get; set; }
    public string BornCountry { get; set; }
    public DateTime? Died { get; set; }
}

修改控制器方法:

public IEnumerable<PrizeDTO> GetPrizes()
{
    var prizes = db.Prizes.Select(prize => new PrizeDTO
                                    {
                                        PrizeID = prize.PrizeID,
                                        Category = prize.Category,
                                        Year = prize.Year,
                                        Laureates = prize.Laureates.Select(laureate => new LaureateDTO
                                        {
                                            LaureateID = laureate.LaureateID,
                                            Surname = laureate.Surname,
                                            FirstName = laureate.FirstName,
                                            Gender = laureate.Gender,
                                            Born = laureate.Born,
                                            BornCountry = laureate.BornCountry,
                                            Died = laureate.Died
                                        }).ToList()
                                    }).ToList();
            
    return prizes;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 21:10:28