Разрывы ответов JSON в веб-API ASP.NET Core 3.1 с настраиваемой оболочкой ответа

Я работаю над проектом веб-API ASP.NET 2.2, который использует оболочку для получения согласованных ответов. После некоторого поиска я обнаружил, что команда следовала реализации из статьи «Пользовательская оболочка для управления исключениями и согласованными ответами».

Это работает, как ожидалось. Теперь мы планируем перейти на ASP.NET Core 3.1. После обновления это не работает должным образом. Я думаю, это произошло из-за серьезных изменений между ASP.NET Core 2.2 и 3.1. Я исправил все это после Microsoft Руководство по переходу с ASP.NET Core 2.2 на 3.0.

Теперь мой ответ JSON от API ломается.

Вот код, который запускается при успешном ответе:

private static Task HandleSuccessRequestAsync(HttpContext context, object body, int code)  
{  
    context.Response.ContentType = "application/json";  
    string jsonString, bodyText = string.Empty;  
    APIResponse apiResponse = null;  


    if (!body.ToString().IsValidJson())  
        bodyText = JsonConvert.SerializeObject(body);  
    else  
        bodyText = body.ToString();  

    dynamic bodyContent = JsonConvert.DeserializeObject<dynamic>(bodyText);  
    Type type;  

    type = bodyContent?.GetType();  

    if (type.Equals(typeof(Newtonsoft.Json.Linq.JObject)))  
    {  
        apiResponse = JsonConvert.DeserializeObject<APIResponse>(bodyText);  
        if (apiResponse.StatusCode != code)  
            jsonString = JsonConvert.SerializeObject(apiResponse);  
        else if (apiResponse.Result != null)  
            jsonString = JsonConvert.SerializeObject(apiResponse);  
        else  
        {  
            apiResponse = new APIResponse(code, ResponseMessageEnum.Success.GetDescription(), bodyContent, null);  
            jsonString = JsonConvert.SerializeObject(apiResponse);  
        }  
    }  
    else  
    {  
        apiResponse = new APIResponse(code, ResponseMessageEnum.Success.GetDescription(), bodyContent, null);  
        jsonString = JsonConvert.SerializeObject(apiResponse);  
    }  

    return context.Response.WriteAsync(jsonString);  
}  

Я отлаживал, пока не попал в return context.Response.WriteAsync(jsonString); внутри метода HandleSuccessRequestAsync(). Все отлично. Но ответ JSON ломается.

Ожидаемый ответ:

{  
    "Version": "1.0.0.0",  
    "StatusCode": 200,  
    "Message": "Request successful.",  
    "Result": [  
        "value1",  
        "value2"  
    ]  
}  

Фактический ответ:

{  
    "Version": "1.0.0.0",  
    "StatusCode": 200,  
    "Message": "Request successful.",  
    "Result":   

Пожалуйста, помогите мне понять, где я ошибаюсь? Это из-за обновления ASP.NET Core 3.1?


person fingers10    schedule 11.03.2020    source источник
comment
Вы имели в виду, что Result в json не имеет данных? Согласно предоставленной вами ссылке и документу о миграции, мой проект 3.1, который был перенесен из проекта 2.2, работал хорошо, и Result имеет значение. Если вы хотите, чтобы сообщество рассмотрело и отладило код, не могли бы вы поделиться полной демонстрацией, которая может воспроизводить проблема ?   -  person Xueli Chen    schedule 12.03.2020
comment
Я получаю данные ответа, но они усечены .. Вот моя ссылка на репо, содержащая демонстрацию с приведенным выше кодом APIResponseWrapper < / а>. Пожалуйста помогите.   -  person fingers10    schedule 12.03.2020
comment
Когда вы говорите: «Все хорошо. Но ответ JSON ломается ». Вы имеете в виду, что объект десериализуется в JSON правильно, но затем обрезается в какой-то момент между return и пользователем? Или вы имеете в виду, что все работает нормально, кроме, что десериализация возвращает усеченный JSON?   -  person Jeremy Caney    schedule 05.04.2020
comment
Вы когда-нибудь находили решение этой проблемы? Не могли бы вы поделиться?   -  person M Akin    schedule 13.07.2020
comment
@M Вы тоже используете обертку ответа? В чем твоя проблема?   -  person fingers10    schedule 13.07.2020


Ответы (1)


У нас была такая же проблема в приложении, где мы использовали настраиваемое промежуточное ПО для изменения тела ответа. Эта страница была полезной:

Внедрение контента с перезаписью ответа в ASP.NET Core 3.x

Нам не нужно было создавать оболочку, как на приведенной выше странице, для HttpResponse.Body, пока мы изменили ContentLength на null перед записью нашего измененного тела в Response. Однако было полезно узнать, что, хотя ASP.NET Core 2.2 не устанавливает ContentLength, когда действие контроллера возвращает его значение и написано тело ответа, ASP.NET Core 3.1 устанавливает ContentLength. В результате, когда мы изменили тело ответа, содержимое стало длиннее, чем задано ContentLength.

У нас есть код, который заменяет тело ответа строкой памяти до того, как ожидается действие контроллера. Это необходимо для того, чтобы иметь возможность захватывать ответ от любого метода контроллера. Затем ответ был изменен, и исходный поток восстановлен до объекта ответа. Затем измененный ответ был записан в тело вместе с исходным потоком.

Произошло то, что, когда промежуточное ПО ожидало ответа контроллера, ответ установил ContentLength. Затем, когда мы написали измененное тело ответа, ContentLength не был обновлен. Таким образом, полученная строка json была усечена. Мы смогли изменить ContentLength на длину измененного содержимого (или использовать null, оба сработали), ЕСЛИ мы изменили длину до записи измененного тела в ответ.

person Hugh Martin    schedule 13.07.2020
comment
Спасибо за то, что поделились своим обучением. Мне это помогло, и это сработало. - person fingers10; 16.07.2020