【问题标题】:After migrating to from .NET core 2.2 to 3.1 api result middleware breaks when adding newtonsoft to project在将 newtonsoft 添加到项目时,从 .NET core 2.2 迁移到 3.1 api 结果中间件中断
【发布时间】:2021-03-12 16:17:51
【问题描述】:

所以我们有一个中间件,它获取我们 API 响应的响应主体并将其包装在“数据”属性下的 ApiResult 类中。

    namespace Web.Api.ApiResult
{
    public class ApiResultMiddleware
    {
        private readonly RequestDelegate next;

        public ApiResultMiddleware(RequestDelegate next)
        {
            this.next = next;
        }

        public async Task Invoke(HttpContext context)
        {
            var originalBody = context.Response.Body;
            var responseBody = string.Empty;
            try
            {
                CsWebException exception = null;

                using (var stream = new MemoryStream())
                {
                    context.Response.Body = stream;

                    try
                    {
                        await next.Invoke(context);
                    }
                    catch (CsWebException e)
                    {
                        exception = e;
                    }

                    stream.Position = 0;
                    responseBody = new StreamReader(stream).ReadToEnd();
                }

                object result = null;

                if (exception != null)
                {
                    result = new ApiResultResponse(null)
                    {
                        ErrorCode = exception.ErrorCode,
                        ErrorData = exception.ErrorData,
                    };
                    context.Response.StatusCode = (int)ApiResultHttpStatusCodeConverter.ConvertToHttpStatusCode(exception.ErrorCode);
                }
                else
                {
                    var data = JsonConvert.DeserializeObject(responseBody);
                    result = new ApiResultResponse(data);
                }

                var buffer = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(
                    result,
                    new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() }));
                if (context.Response.StatusCode != StatusCodes.Status204NoContent)
                {
                    using (var output = new MemoryStream(buffer))
                    {
                        var test = JsonConvert.DeserializeObject<ApiResultResponse>(new StreamReader(output).ReadToEnd());
                        await output.CopyToAsync(originalBody);
                    }
                }
            }
            catch (JsonReaderException)
            {
                var result = new ApiResultResponse(responseBody);
                var buffer = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(
                    result,
                    new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() }));
                using (var output = new MemoryStream(buffer))
                {
                    await output.CopyToAsync(originalBody);
                }
            }
            finally
            {
                context.Response.Body = originalBody;
            }
        }
    }

    public static class ApiResultMiddlewareExtensions
    {
        public static IApplicationBuilder UseApiResultMiddleware(this IApplicationBuilder builder)
        {
            return builder.UseMiddleware<ApiResultMiddleware>();
        }
    }
}

它在 .NET core 2.2 中运行良好,甚至在迁移到 3.1 并使用 Sytem.Text.Json 中的构建之后,但因为我们在补丁端点中需要 newtonsoft。通过添加它

services.AddControllers().AddNewtonsoftJson();

返回的 JSON 在中间某处被剪切。我在编写它之前添加了测试变量并反序列化了 JSON,它看起来很好,但是在我们的前端解析 i 时它不是。

一个例子是写入正文的 jsonbeeing 如下所示:

"{\"errorCode\":0,\"errorData\":null,\"data\":{\"previousWorkingDayWorkOrders\":[],\"nextWorkingDayWorkOrders\":[],\"todaysWorkOrders\":[],\"nonInvoicedWorkOrders\":[{\"workOrderId\":1232753.0,\"employeeNumber\":5000000037.0,\"employeeName\":\"VERKADM, VERKADM\",\"vehicleRegistrationNumber\":\"PXG948\",\"dealerOrderNumber\":null,\"bookingNumber\":null,\"preplannedDate\":null,\"workOrderStatus\":7,\"shortageIndicator\":true,\"customerWaiting\":false,\"vehicleDescriptionShort\":\"Volvo V40 Cross Country\",\"vehicleModelYear\":2018,\"colorDescription\":\"Blå\",\"fuelDescription\":\"Diesel\",\"email\":null,\"customer\":{\"customerNumber\":null,\"name\":\"Volvo Bil I Göteborg AB\",\"telephone\":null,\"email\":null,\"customerType\":1},\"mainPayerCustomerType\":1,\"notes\":null,\"vehicleIdentificationNumber\":\"YV1MZ79L0J2139968\"}],\"webWorkOrders\":[]}}"

当在邮递员中收到相同的响应时,它无法解析为 json,因为它被切断了,在计划文本中它看起来像:

{"errorCode":0,"errorData":null,"data":{"previousWorkingDayWorkOrders":[],"nextWorkingDayWorkOrders":[],"todaysWorkOrders":[{"workOrderId":1229253.0,"employeeNumber":5000000037.0,"employeeName":"VERKADM, VERKADM","vehicleRegistrationNumber":"PXG948","dealerOrderNumber":null,"bookingNumber":"349","preplannedDate":"2020-02-06T07:00:00","workOrderStatus":5,"shortageIndicator":true,"customerWaiting":false,"vehicleDescriptionShort":"Volvo V40 Cross Country","vehicleModelYear":2018,"colorDescription":"Blå","fuelDescription":"Diesel","email":null,"customer":{"customerNumber":null,"name":"Volvo Bil I Göteborg AB","telephone":null,"email":null,"customerType":1},"mainPayerCustomerType":1,"notes":null,"vehicleIdentificationNumber":"YV1MZ79L0J2139968"}],"nonInvoicedWorkOrders":[{"workOrderId":1232753.0,"employeeNumber":5000000037.0,"employeeName":"VERKADM, VERKADM","vehicleRegistrationNumber":"PXG948","dealerOrderNumber":null,"bookingNumber":null,"preplannedDate":null,"workOrderStatus":7,"shortageIndicator":true,"customerWaiting":false,"vehicleDescriptionShort":"Volvo V40 Cross Country","vehicleModelYear":2018,"colorDescription":"Blå","fuelDescription":"Diesel","email":null,"customer":{"customerNumber":null,"name":"Volvo Bil I Göteborg AB","telephone":null,"email":null,"customerType":1},"mainPayerCustomerType":1,"notes":null,"vehicleIdentificationNumber":"Y

知道为什么这不起作用吗?

编辑:我还应该指出,通过删除中间件 app.UseApiResultMiddleware(); 一切正常,但我们仍然想包装我们的回复

编辑 2。感谢 dbc 的回复,我设法解决了这个问题。通过将响应内容的长度设置为缓冲区的长度,它可以完美地工作。

context.Response.ContentLength = buffer.Length;

让我感到困惑的是,在没有使用 System.Text.Json 设置长度以及我们使用 .Net core 2.2 时,这一事实仍然有效

【问题讨论】:

  • 欢迎您!您是否尝试过刷新响应流?
  • 谢谢。我试过冲洗它,但这似乎不是问题。
  • 只是一个简短的说明,你知道{{}}作为json无效吗?
  • 您的 json 无效
  • 对不起,我贴出来的json其实是代码中test变量中解析出来的实际json到匿名对象的解析值。我更新为使用序列化的 json 发布

标签: c# .net json


【解决方案1】:

其他可能,你没有跟随the migration guide 到.NET Core 3.0。

使用Microsoft.AspNetCore.Mvc.NewtonsoftJson 包而不是Newtonsoft.Json 包。

【讨论】:

  • 是的,我们确实遵循了迁移指南,并且我们使用的是 Microsoft.AspNetCore.Mvc.NewtonsoftJson。如果我删除该行:app.UseApiResultMiddleware(); ,对象的解析工作。但随后响应不会被包裹在 ApiResultResponse 类中
【解决方案2】:

你用

添加了 NewtonsoftJson

services.AddControllers().AddNewtonsoftJson();

但我不确定中间件是否能够访问它(之前从未尝试过这种服务注册方法)。

您是否尝试使用旧的添加它?

services.AddMvc().AddNewtonsoftJson();

【讨论】:

【解决方案3】:

我遇到了同样的问题。但是在中间件服务中添加以下行后我已经成功了。

 string plainBodyText = await new StreamReader(context.response.Body).ReadToEndAsync();    
context.Response.ContentLength = plainBodyText.Length;

【讨论】:

    猜你喜欢
    • 2021-08-31
    • 1970-01-01
    • 2021-09-02
    • 2020-07-26
    • 1970-01-01
    • 2020-05-28
    • 2020-08-22
    • 2020-05-06
    • 2020-05-27
    相关资源
    最近更新 更多