【问题标题】:Azure CosmosDB + NetCore 3.1 : System.Text.Json.JsonException: A possible object cycle was detected which is not supportedAzure Cosmos DB + Net Core 3.1:System.Text.Json.JsonException:检测到不支持的可能对象循环
【发布时间】:2020-10-02 22:15:02
【问题描述】:

我的 API (Net core 3.1) 对 CosmosDB 的特定调用遇到了问题 我收到一个错误回复:

"fail: Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware[1]
      An unhandled exception has occurred while executing the request.
System.Text.Json.JsonException: A possible object cycle was detected which is not supported."

我的 User_Profile 类相当简单:

using Newtonsoft.Json;

namespace API
{
    public class User_Profile
    {
        [JsonProperty("id")]
        public string                   Id                          { get; set; }
        public string                   Password                    { get; set; }
        public string                   Role                        { get; set; }
    }
}

调用数据库方法:

public async Task<User_Profile> GetUserAsync (string id)
        {
            try
            {
                User_Profile foundUser = await ctner_Users.ReadItemAsync<User_Profile>(id, new PartitionKey(id));
                return foundUser;
            }
            catch (Exception e)
            {
                _logger.LogWarning("AddUserAsync failed : " + e);
                return null ;
            }
        }

这是 cosmos db explorer 中显示的文档:

{
    "id": "romain",
    "Password": "Password",
    "Role": "User",
    "_rid": "VqgQAP51mcUCAAAAAAAAAA==",
    "_self": "dbs/VqgQAA==/colls/VqgQAP51mcU=/docs/VqgQAP51mcUCAAAAAAAAAA==/",
    "_etag": "\"4300e1b0-0000-0100-0000-5ee44ce00000\"",
    "_attachments": "attachments/",
    "_ts": 1592020192
}

这是控制器中的方法:

[HttpPost("auth")]
        public ActionResult<User_Profile> AuthUser ([FromBody] User_Profile authUser)
        {
            var user = _db.GetUserAsync(authUser.Id);
            if (user != null)
            {
                return Ok(user);
            }
            else
            {
                return NotFound();
            }
        }

一直在尝试调试/消除故障/发现问题出在哪里很长一段时间,所以我已经删除了很多以前的代码,比如密码检查、模型验证等......并试图保持最低限度以缩小范围,但即使这样也会给我相同的循环错误消息。知道我的用户配置文件类中只有 3 个字符串,我看不到循环引用问题。

我尝试过的一件事是将 json 更新为上次预览并添加引用处理,并将其设置为保存器:相反,我收到一条非常长的错误消息,显示似乎每个程序集版本都可能存在。

注意:对数据库的其他调用正在工作..创建用户,或访问其他容器,从中读取,等等......实际上只是这个特殊调用让我返回了那个错误,我目前在完全失去了那个。任何帮助将不胜感激。

编辑:如果我在 startup.cs 中替换为

services.AddControllers().AddNewtonsoftJson(options =>
                options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
            );

然后我在控制器上尝试相同方法时得到的消息是非常冗长的(我已经剪掉了所有的组装部分):

{
    "stateMachine": {
        "<>1__state": 0,
        "<>t__builder": {},
        "id": "romain",
        "<>4__this": {}
    },
    //BIG CONTEXT SECTION HERE, ABOUT 0.5 MB of text...
    "result": {
        "id": "romain",
        "password": "Password",
        "role": "User"
    },
    "id": 1808,
    "exception": null,
    "status": 5,
    "isCanceled": false,
    "isCompleted": true,
    "isCompletedSuccessfully": true,
    "creationOptions": 0,
    "asyncState": null,
    "isFaulted": false
}

编辑 2:如果我尝试检索列表而不是单个项目,它可以工作:

[HttpPost("auth2")]
        public async Task<ActionResult<List<User_Profile>>> GetUsers ([FromBody] User_Profile authUser)
        {
            List<User_Profile> list = await _db.GetUsersAsync(authUser.Id);
            return Ok(list);
        }
public async Task<List<User_Profile>> GetUsersAsync (string id)
        {
            try
            {
                string queryString = "SELECT * FROM c WHERE c.id='"+id+"'";
                var query = ctner_Users.GetItemQueryIterator<User_Profile>(new QueryDefinition(queryString));
                List<User_Profile> results = new List<User_Profile>();
                while (query.HasMoreResults)
                {
                    var response = await query.ReadNextAsync();
                    results.AddRange(response.ToList());
                }

                return results;
            }
            catch (Exception e)
            {
                return null;
            }
        }

问题似乎与我没有正确使用的“ReadItemAsync”有关,或者我正在使用的版本有问题。

【问题讨论】:

  • 您确定问题出在 db 调用中,而不是在从正文中检索 User_Profile 中吗?
  • vivek :我试过了,结果将是一个非常长的汇编版本信息,等等...... Gusman :如果我这样做的话,肯定是的:Console.WriteLine(authUser.Id); ,就在 var user = _db.GetUserAsync(authUser.Id); 之前它确实显示“罗马”

标签: c# asp.net-core azure-cosmosdb


【解决方案1】:

我找到了一个解决方案,与报告的错误信息相差甚远。

我不得不将控制器变成async Task,而不是之前的。

控制器必须是:

    [HttpPost("auth")]
    public async Task<ActionResult<User_Profile>> AuthUser ([FromBody] User_Profile authUser)
    {
        var user = await _db.GetUserAsync(authUser.Id);
        if (user != null)
        {
            return Ok(user);
        }
        else
        {
            return NotFound();
        }
    }

代替:

    [HttpPost("auth")]
    public ActionResult<User_Profile> AuthUser ([FromBody] User_Profile authUser)
    {
        var user = _db.GetUserAsync(authUser.Id);
        if (user != null)
        {
            return Ok(user);
        }
        else
        {
            return NotFound();
        }
    }

我不确定我是否可以解释那个,但它解决了这个问题。

【讨论】:

  • 在前一个中,您的用户变量包含一个任务,因此返回 Ok(user) 正在尝试序列化一个任务,而不是实际的 User_Profile。 Await 解决了这个问题,因此用户变量包含可以安全序列化的实际用户
猜你喜欢
  • 2020-07-06
  • 2021-08-30
  • 2020-03-30
  • 2021-12-09
  • 2020-04-27
  • 2021-03-17
  • 2021-08-01
  • 2020-07-26
  • 2020-05-10
相关资源
最近更新 更多