ReadStringAsSync()仅返回部分内容

时间:2019-04-18 16:45:50

标签: c# asp.net-core .net-core asp.net-core-webapi dotnet-httpclient

我有一个简单的ASP.NET Core 2.2控制器操作,即使从POSTMAN发送请求,该操作也会返回不完整的JSON。

代码运行良好,直到包含相关实体“ Books”的导航属性为止。正如我在调试时所看到的,从IQueryable对象上的ToList()方法正确返回了结果。但是,由于某种原因,当ReadAsStringAsync()运行时,它仅返回预期JSON结果的一部分。

下面是API的代码:

    [HttpPost]
    [Route("api/TestEntity/ListTest")]
    public async Task<ActionResult<IEnumerable<TestEntityPerson>>> ListTest()
    {
        var query = _context.Persons
            .Include(p => p.Books)
            .AsQueryable().Take(5);
        var results = await Task.FromResult(Json(query.ToList()));
        return results;
    }

我在客户端收到的结果(只是预期结果的一部分)是:

[{"$type":"Identica.My.Bonus.Entities.TestEntityPerson, Identica.My.Bonus","name":"Susan","balance":240749.08345506949,"age":56,"books":[{"$type":"Identica.My.Bonus.Entities.TestEntityBook, Identica.My.Bonus","title":"SRWZLSRKQNYKPY","author":"VEJZP","price":13.334878714911119,"personId":"f24dbe36-1f99-4a59-3cb7-08d6c4048ace"

关于我可以尝试解决此问题的任何指示?我找不到有关堆栈溢出的任何相关问题。

编辑:仅当相关实体上有指向原始实体的导航属性时,才会发生这种情况。当我删除此属性后,问题就消失了。

这是客户端代码:

class Program
{
    static async Task Main(string[] args)
    {
        Console.WriteLine("Press any key to run query...");
        Console.Read();

        MediaTypeWithQualityHeaderValue mediaTypeJson = new MediaTypeWithQualityHeaderValue("application/json");

        List<MediaTypeFormatter> formatters = new List<MediaTypeFormatter> {
            new JsonMediaTypeFormatter {
                SerializerSettings = new JsonSerializerSettings
                {
                    TypeNameHandling = TypeNameHandling.Objects
                }
            }
        };

        using (HttpClient httpClient = new HttpClient() { BaseAddress = new Uri("https://localhost:44359/") })
        {
            httpClient.DefaultRequestHeaders.Accept.Clear();
            httpClient.DefaultRequestHeaders.Accept.Add(mediaTypeJson);

            Expression<Func<TestEntityPerson, bool>> expressionFilter =
                t => (t.Balance > 240000 || t.Age < 25) && 
                (t.Books == null || t.Books.Any(b => b.Price < 7 || b.Title.StartsWith('A')));

            var filterNode = expressionFilter.ToExpressionNode();

            Expression<Func<IQueryable<TestEntityPerson>, IOrderedQueryable<TestEntityPerson>>> expressionOrderBy = t => t.OrderByDescending(x => x.Balance);

            var orderByNode = expressionOrderBy.ToExpressionNode();

            Pagination pagination = new Pagination() { Start = 0, Limit = 10 };

            QueryOptionsNodes queryOptions = new QueryOptionsNodes()
            {
                FilterExpressionNode = filterNode,
                SortingExpressionNode = orderByNode,
                Pagination = pagination
            };

            try
            {
                Console.WriteLine("Sending request...");

                var response = await httpClient.PostAsync("api/TestEntity/List", queryOptions, formatters[0], mediaTypeJson, CancellationToken.None);
                response.EnsureSuccessStatusCode();

                Console.WriteLine("Reading Response request...");

                var result = await response.Content.ReadAsAsync<IEnumerable<TestEntityPerson>>(formatters, CancellationToken.None);
                ShowEntities(result);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }

            try
            {
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }

        Console.WriteLine("Press any key to exit...");

        Console.ReadLine();
        Console.ReadLine();
    }

    private static void ShowEntities(IEnumerable<TestEntityPerson> testEntities)
    {
        foreach (var entity in testEntities)
        {
            Console.WriteLine("{0}) {1} Age = {2} Balance = {3}", entity.Id, entity.Name, entity.Age, entity.Balance);
            if (entity.Books != null)
            {
                Console.WriteLine("Books:");
                foreach (var book in entity.Books)
                {
                    Console.WriteLine("-- {0}) {1} Price = {2}", book.Id, book.Title, book.Price);
                }
            }
            Console.WriteLine();
        }
    }
}

1 个答案:

答案 0 :(得分:0)

“相关实体”上有多余的导航属性指向“原始实体”的问题。

public class TestEntityPerson : BaseEntity<int>
{
    public string Name { get; set; }
    public double Balance { get; set; }
    public int Age { get; set; }

    public List<TestEntityBook> Books { get; set; }
}

及相关实体:

public class TestEntityBook : BaseEntity<int>
{
    public string Title { get; set; }
    public string Author { get; set; }
    public double Price { get; set; }

    public Guid TestEntityPersonId { get; set; }

    // The problematic property
    public TestEntityPerson TestEntityPerson { get; set; }
}

当我从Book实体中删除TestEntityPerson属性时,问题已解决。

编辑:我想这不是一个真正的解决方案,因为具有反向导航属性应该可以,但是在这种情况下,这会引起问题。