【问题标题】:How do you implement System.Text.Json.Serialization.ReferenceHandler.Preserve in a Blazor WebAssemby application如何在 Blazor WebAssemby 应用程序中实现 System.Text.Json.Serialization.ReferenceHandler.Preserve
【发布时间】:2021-03-23 11:27:23
【问题描述】:

据我了解,当您在对象模型中定义循环引用时,您可以使用此设置来解决出现以下错误的问题:

JsonException:检测到不支持的可能对象循环。这可能是由于循环或对象深度大于最大允许深度 32 造成的。

但是我无法成功实施它以使其正常工作。如果有人可以提供有关需要做什么的详细说明,将不胜感激!

我曾考虑将应用程序切换为使用 Newtonsoft.JSON,但据我所知,这在 Blazor WebAssembly 应用程序中不可行?

2020 年 12 月 12 日更新

我在试图弄清楚如何实现 ReferenceHandler.Preserve 时发现的最接近的文章是:

https://github.com/dotnet/runtime/issues/42584

https://github.com/dotnet/aspnetcore/issues/28286

根据这些文章,我尝试实施以下解决方案,但都不起作用...

第一次尝试我在我的服务器项目的 Startup.cs 类中实现了以下代码:

services.AddControllersWithViews().AddJsonOptions(options =>
            {
                options.JsonSerializerOptions.ReferenceHandler = System.Text.Json.Serialization.ReferenceHandler.Preserve;
            });

第二次尝试我在我的服务器项目的 Startup.cs 类中实现了以下代码:

services.AddControllersWithViews(options =>
            {
                options.OutputFormatters.RemoveType<SystemTextJsonOutputFormatter>();
                options.OutputFormatters.Add(new SystemTextJsonOutputFormatter(new JsonSerializerOptions(JsonSerializerDefaults.Web)
                {
                    ReferenceHandler = ReferenceHandler.Preserve
                }));
            });

更新 2020 年 12 月 12 日上午 11:12 CST

在将我的服务器项目更改为面向 .NET 5 并尝试上面的两个代码选项后,我现在在我的应用程序的每个页面上都收到以下类型的错误:

Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100] 未处理的异常呈现组件:无法将 JSON 值转换为 BusinessManager.Shared.Models.EmploymentBenefit[]。路径:$ |行号:0 | BytePositionInLine:1。

重现原始问题的步骤

创建一个新的 Blazor WebAssembly 应用程序

在共享项目中定义一个包含子对象集合的父类,如下所示:

public virtual List<Child> Children{ get; set; } = new List<Child>();

在 Child 类中定义一个引用其父级的属性,如下所示:

public virtual Parent Parent{ get; set; }

然后,我使用实体框架来生成数据库对象。创建一个返回父对象及其子对象的 web api 函数:

[HttpGet("{id}")]
        public async Task<IActionResult> Get(Guid id)
        {
            var returnValue = await db.Parents
                .Include(aa => aa.Children)
                .FirstOrDefaultAsync(aa => aa.ParentId== id);
            return Ok(returnValue);
        }

然后尝试通过调用这个web api函数在页面上渲染父子集合。

【问题讨论】:

  • 除此之外,您写道,但是我无法成功实现它以使其正常工作。 - 那么您能否分享一个 minimal reproducible example 来显示什么没有工作?来自How to Ask:帮助其他人重现问题...如果您的问题与您编写的代码有关,您应该包含一些...包含足够的代码以允许其他人重现问题。
  • 这里是一个使用ReferenceHandler.Preserve的例子:dotnetfiddle.net/t2EkHR。 请注意,ReferenceHandler.Preserve 仅适用于 .Net 5 或更高版本。 诊断您在编写时提到的问题我无法成功实现它以使其正常工作 我们需要查看minimal reproducible example,其中包含您编写的不起作用的代码。
  • 用代码示例更新了我的帖子。我想知道 .Net 5 或更高版本是否至少不是 Blazor WebAssembly 应用程序问题的一部分,因为我没有看到您可以将 .Net 5 与 Blazor WebAssembly 一起使用,尽管我找到了所有不同版本的框架有点混乱,很难保持直截了当。但是,代码在我的更改到位后编译得很好。我在我的服务器项目中引用 System.Net.Http.Json 版本 5.0.0。我的客户端项目面向 .NET Standard 2.1,我的服务器项目面向 .NET Core 3.1
  • 您的第二个序列化代码有效,但它创建的 json 包含 $id、$values 和 $ref 等字段,System.Text.Json 无法反序列化。

标签: json.net blazor-webassembly system.text.json


【解决方案1】:

这是我用我的。在 Startup.cs 添加这个

services.AddMvc().AddJsonOptions(o =>
        {
            o.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.Preserve;
        });

【讨论】:

    【解决方案2】:

    将我的服务器项目更改为面向 .NET 5 并尝试两种代码后 上面的选项我现在在每个页面上都收到以下类型的错误 在我的应用程序中:

    Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100] 未处理的异常呈现组件:JSON 值不能是 转换为 BusinessManager.Shared.Models.EmploymentBenefit[]。小路: $ |行号:0 | BytePositionInLine:1。

    您是否也在客户端启用ReferenceHandler.Preserve?否则客户端中的JsonSerializer 不会知道元数据。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-04-16
      • 2021-06-21
      • 1970-01-01
      • 2021-02-04
      • 2010-10-16
      • 2021-01-05
      • 1970-01-01
      相关资源
      最近更新 更多