修复 C# Web API 中的循环引用错误

问题描述 投票:0回答:1

我有一个用 C# 编写的相当简单的 Web API,使用 EF。这个想法基本上是一个待办事项应用程序,具体关系是:一个用户可以有许多待办事项列表,每个待办事项列表可以有许多待办事项。

这是我的数据模型:

public class User
{
    public Guid Id { get; set; }
    public string? Name { get; set; }
    public string? Email { get; set; }
    public string? Password { get; set; } // Be sure to properly hash and salt passwords
    public string? ProfilePhotoUrl { get; set; } // Store the URL to the user's profile photo
    public List<ToDoList>? ToDoLists { get; set; } // A user can have multiple to-do lists
}

public class ToDoList
{
    public Guid Id { get; set; }
    public string? Title { get; set; }
    public List<ToDo>? ToDos { get; set; } // Each to-do list contains multiple to-dos

    // Foreign Key to User
    public Guid UserId { get; set; }
    public User? User { get; set; }
}
public class ToDo
{
    public Guid Id { get; set; }
    public string? Name { get; set; }
    public string? Description { get; set; }
    public bool? InProgress { get; set; }
    public bool? IsComplete { get; set; }
    public DateTime Created { get; set; } = DateTime.Now;

    public ToDoList? ToDoList { get; set; } 
    public Guid? ToDoListId{ get; set; }
}

我有一个控制器,允许用户注册、登录等。我想做的一件事是检索用户可能拥有的每个待办事项列表。我在服务中有代码:

    public Task<User> GetToDoListsForUsers(Guid userId)
    {
        return _context.Users
            .Include(u => u.ToDoLists)
            .FirstOrDefaultAsync(u => u.Id == userId);
    }

然后由控制器调用:

    [HttpGet("{userId}/todolists")]
    public async Task<ActionResult<IEnumerable<ToDoList>>> GetToDoListsForUser(Guid userId)
    {
        var user = await _userService.GetToDoListsForUsers(userId);

        if (user == null)
        {
            return NotFound("User not found");
        }

        var toDoLists = user.ToDoLists;

        if (toDoLists.Count == 0)
        {
            return NotFound("user has no lists");
        }

        return Ok(toDoLists);
    }

但是,当我运行此命令时,出现以下错误:


      An unhandled exception has occurred while executing the request.
      System.Text.Json.JsonException: A possible object cycle was detected. This can either be due to a cycle or if the object depth is larger than the maximum allowed depth of 32. Consider using ReferenceHandler.Preserve on JsonSerializerOptions to support cycles. Path: $.User.ToDoLists.User.ToDoLists.User.ToDoLists.User.ToDoLists.User.ToDoLists.User.ToDoLists.User.ToDoLists.User.ToDoLists.User.ToDoLists.User.ToDoLists.Id.

我相信这是因为用户有对 ToDoList 的引用,而 ToDoList 有对用户的引用,但我需要这两种方式的引用,因为它们是外键。

我还在网上遇到了这个解决方案,添加了这些行:

        var jsonSettings = new JsonSerializerOptions
        {
            ReferenceHandler = ReferenceHandler.Preserve,
        };

        var serializedUser = JsonSerializer.Serialize(user, jsonSettings);
        var deserializedUser = JsonSerializer.Deserialize<User>(serializedUser, jsonSettings);

        var toDoLists = deserializedUser.ToDoLists;

到控制器方法,但这也不起作用。

有什么帮助可以解决这个问题吗?

c# asp.net asp.net-mvc entity-framework circular-reference
1个回答
0
投票

TBH 找到的“解决方案”没有任何意义,使用与

ReferenceHandler.Preserve
相同的设置只会恢复引用。

手动返回序列化数据即可:

var serializedLists = JsonSerializer.Serialize(user.ToDoLists, jsonSettings);
return Content();

或者更好地全局应用

ReferenceHandler.Preserve
设置:

builder.Services.AddControllers()
    .AddJsonOptions(options =>
        options.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.Preserve);

了解更多 - 避免或控制 Entity Framework Core 中的循环引用 .

© www.soinside.com 2019 - 2024. All rights reserved.