【问题标题】:JSON response breaks in ASP.NET Core 3.1 Web API with custom response wrapper带有自定义响应包装器的 ASP.NET Core 3.1 Web API 中的 JSON 响应中断
【发布时间】:2020-06-23 11:14:19
【问题描述】:

我正在开发一个 ASP.NET 2.2 Web API 项目,该项目使用包装器来产生一致的响应。经过一番搜索,我发现团队遵循文章“A Custom Wrapper For Managing Exceptions And Consistent Responses”中的实现。

这按预期工作。现在我们计划升级到 ASP.NET Core 3.1。升级后,这不能按预期工作。我认为这是由于 ASP.NET Core 2.2 和 3.1 之间的重大变化。我按照 Microsoft 的 Migrate from ASP.NET Core 2.2 to 3.0 指南修复了所有这些问题。

现在我来自 API 的 JSON 响应中断了。

这是响应成功时执行的代码:

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

我进行了调试,直到它在 HandleSuccessRequestAsync() 方法中找到了 return context.Response.WriteAsync(jsonString);。一切顺利。但 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升级了吗?

【问题讨论】:

  • 你的意思是json中的Result没有数据吗?根据您提供的链接和迁移文档,我从 2.2 项目迁移的 3.1 项目运行良好,Result 具有价值。如果您希望社区审查和调试代码,您可以分享一个完整的演示,可以重现问题?
  • 我正在获取响应数据,但它被截断了。这是我的回购链接,其中包含上面代码APIResponseWrapper 的演示。请帮忙。
  • 当你说,“一切都很好。但是 JSON 响应中断了。”您的意思是该对象被正确反序列化为 JSON,但随后在 return 和用户之间的某个时间点被截断?还是您的意思是一切正常,除了反序列化返回截断的 JSON?
  • 您找到解决此问题的方法了吗?可以分享一下吗?
  • @M Akin 您正在使用响应包装器吗?你有什么问题?

标签: c# json serialization asp.net-core-webapi asp.net-core-3.1


【解决方案1】:

我们在使用自定义中间件更改响应正文的应用程序中遇到了同样的问题。此页面很有帮助:

Content Injection with Response Rewriting in ASP.NET Core 3.x

我们不必像上面页面那样为 HttpResponse.Body 创建一个包装器,只要我们在将更改后的正文写入响应之前将 ContentLength 更改为 null。虽然了解 ASP.NET Core 2.2 在控制器操作返回其值并写入响应正文时未设置 ContentLength 时,但 ASP.NET Core 3.1 确实设置了 ContentLength,这很有帮助。结果,当我们更改响应正文时,内容变得比设置的 ContentLength 长。

我们有代码在等待控制器操作之前用内存字符串替换响应正文。这是为了能够捕获来自任何控制器方法的响应。然后响应被更改,原始流恢复到响应对象。然后将更改后的响应写入正文,并保留其原始流。

发生的情况是,当中间件等待控制器响应时,响应设置了 ContentLength。然后,当我们编写更改后的响应正文时,ContentLength 没有更新。所以收到的 json 字符串被截断了。我们能够将 ContentLength 更改为更改内容的长度(或使用 null,两者都有效),如果我们更改长度将更改的正文写入响应之前。

【讨论】:

  • 感谢分享您的学习。它帮助了我,并且奏效了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-03
  • 2018-04-28
  • 1970-01-01
  • 2018-12-25
  • 2020-11-14
相关资源
最近更新 更多