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

Blazor Web App使用Syncfusion ComboBox遭遇JSON循环引用问题

解决Blazor中Syncfusion ComboBox循环引用JSON序列化错误

问题场景

我基于EF Core开发Blazor Web App,在页面使用Syncfusion ComboBox展示数据时,触发了循环引用导致的JSON序列化错误。

ComboBox代码:

<SfComboBox TValue="Contact" TItem="Contact" @bind-Value="item.Owner" DataSource="Contacts" Placeholder="Besitzer">
    <ComboBoxFieldSettings Value="@nameof(Contact.FullName)"></ComboBoxFieldSettings>
</SfComboBox>

错误追踪

Error: System.Text.Json.JsonException: 检测到可能的对象循环。这可能是由于循环引用,或者对象深度超过了允许的最大深度64。请考虑在JsonSerializerOptions上使用ReferenceHandler.Preserve来支持循环引用。路径: $.Items.Owner.Items.Owner.Items.Owner.Items.Owner.Items.Owner.Items
...
...
JsonSerializerOptions options, WriteStack& state)
   at System.Text.Json.Serialization.JsonConverter`1.TryWrite(Utf8JsonWriter writer, T& value, JsonSerializerOptions options, WriteStack& state)
   at System.Text.Json.Serialization.JsonConverter`1.WriteCore(Utf8JsonWriter writer, T& value, JsonSerializerOptions options, WriteStack& state)
   at System.Text.Json.Serialization.Metadata.JsonTypeInfo`1.Serialize(Utf8JsonWriter writer, T& rootValue, Object rootValueBoxed)
   at System.Text.Json.JsonSerializer.WriteString[TValue](TValue& value, JsonTypeInfo`1 jsonTypeInfo)
   at System.Text.Json.JsonSerializer.Serialize[TValue](TValue value, JsonSerializerOptions options)
   at Syncfusion.Blazor.DropDowns.SfDropDownList`2.GetDataByValue(TValue ddlValue)
   at Syncfusion.Blazor.DropDowns.SfDropDownList`2.InitValueAsync()
   at Syncfusion.Blazor.DropDowns.SfDropDownList`2.OnAfterRenderAsync(Boolean firstRender)
   at Syncfusion.Blazor.DropDowns.SfComboBox`2.OnAfterRenderAsync(Boolean firstRender)
   at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle, ComponentState owningComponentState)

已尝试的无效配置

我曾配置JSON引用处理,但未生效:

builder.Services.Configure<Microsoft.AspNetCore.Http.Json.JsonOptions>(options => options.SerializerOptions.ReferenceHandler = ReferenceHandler.Preserve);
builder.Services.ConfigureHttpJsonOptions(jsonOptions =>
{
    jsonOptions.SerializerOptions.ReferenceHandler = ReferenceHandler.Preserve;
});

实体类定义

public class Item
{
    public Contact Owner { get; set; }
}

public class Contact
{
    public List<Item> Items { get; set; } = new List<Item>();
}

解决方案

方案1:禁用EF Core延迟加载(推荐)

循环引用的根源是EF Core默认的延迟加载机制——加载Contact时会自动拉取关联的Items,每个Item又关联回Contact,形成无限循环。可以通过两种方式解决:

  • 全局禁用延迟加载:
builder.Services.AddDbContext<YourDbContext>(options =>
    options.UseSqlServer("你的连接字符串")
           .UseLazyLoadingProxies(false)); // 关闭延迟加载代理
  • 单个查询层面禁用:
// 不加载关联的Items集合
var contacts = await _dbContext.Contacts.AsNoTracking().ToListAsync();

// 或者仅选择ComboBox需要的字段
var contacts = await _dbContext.Contacts.Select(c => new Contact
{
    Id = c.Id,
    FullName = c.FullName
    // 不包含Items属性,切断循环
}).ToListAsync();

方案2:为Syncfusion组件单独配置序列化选项

你之前配置的是HTTP请求的JSON序列化选项,但Syncfusion组件内部使用独立的配置。需要通过SyncfusionBlazorOptions设置:

builder.Services.AddSyncfusionBlazor(options =>
{
    options.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.Preserve;
});

方案3:使用DTO(数据传输对象)

创建仅包含ComboBox所需字段的DTO类,彻底切断循环引用:

public class ContactDto
{
    public int Id { get; set; }
    public string FullName { get; set; }
}

查询时转换为DTO:

var contactDtos = await _dbContext.Contacts.Select(c => new ContactDto
{
    Id = c.Id,
    FullName = c.FullName
}).ToListAsync();

修改ComboBox的类型适配DTO:

<SfComboBox TValue="ContactDto" TItem="ContactDto" @bind-Value="selectedOwner" DataSource="contactDtos" Placeholder="Besitzer">
    <ComboBoxFieldSettings Value="@nameof(ContactDto.FullName)"></ComboBoxFieldSettings>
</SfComboBox>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 21:26:20