ReadStringAsSync () Возвращает только часть содержимого - PullRequest
0 голосов
/ 18 апреля 2019

У меня есть простое действие контроллера ASP.NET Core 2.2, которое возвращает неполный JSON даже при отправке запроса из POSTMAN.

Код работает нормально, пока я не включу свойство навигации для связанной сущности «Книги». Результаты правильно возвращаются из метода ToList () объекта IQueryable, как я вижу при отладке. Но по какой-то причине при запуске 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 голосов
/ 19 апреля 2019

Проблема в том, что в «связанном объекте» было ненужное навигационное свойство, указывающее назад на «исходный объект».

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; }
}

Когда я удалил свойство TestEntityPerson из сущности Book, проблема была решена.

РЕДАКТИРОВАТЬ: я предполагаю, что это не реальное решение, так как должно быть нормально иметь свойства обратной навигации, но в этом случае это вызывало проблему.

...