episerver / netcore-preview

This repository is a preview providing early access to the latest Optimizely (formerly Episerver) product packages targeting .NET 5.
43 stars 9 forks source link

Unknow exception when opening av page tree structure in Episerver #97

Closed oyvindwh closed 3 years ago

oyvindwh commented 3 years ago

Sub pages contains both Arabic and Chinese translated pages.

image

@barteksekula, can be seen in the integration environment. More details can be shared in Teams.

@lunchin

oyvindwh commented 3 years ago

Stacktrace:

fail: Microsoft.AspNetCore.Server.IIS.Core.IISHttpServer[2] Connection ID "17077649797189468231", Request ID "80000048-0002-ed00-b63f-84710c7967bb": An unhandled exception was thrown by the application. System.InvalidOperationException: Synchronous operations are disallowed. Call WriteAsync or set AllowSynchronousIO to true instead. at Microsoft.AspNetCore.Server.IIS.Core.HttpResponseStream.Write(Byte[] buffer, Int32 offset, Int32 count) at Microsoft.AspNetCore.Server.IIS.Core.WrappingStream.Write(Byte[] buffer, Int32 offset, Int32 count) at System.IO.Compression.DeflateStream.WriteDeflaterOutput() at System.IO.Compression.DeflateStream.WriteCore(ReadOnlySpan1 buffer) at System.IO.Compression.DeflateStream.Write(Byte[] array, Int32 offset, Int32 count) at System.IO.Compression.GZipStream.Write(Byte[] array, Int32 offset, Int32 count) at WebMarkupMin.AspNetCore5.BodyWrapperStreamBase.Write(Byte[] buffer, Int32 offset, Int32 count) at Microsoft.AspNetCore.ResponseCompression.ResponseCompressionBody.Write(Byte[] buffer, Int32 offset, Int32 count) at Microsoft.AspNetCore.WebUtilities.HttpResponseStreamWriter.Write(String value) at Newtonsoft.Json.Utilities.JavaScriptUtils.WriteEscapedJavaScriptString(TextWriter writer, String s, Char delimiter, Boolean appendDelimiters, Boolean[] charEscapeFlags, StringEscapeHandling stringEscapeHandling, IArrayPool1 bufferPool, Char[]& writeBuffer) at Newtonsoft.Json.JsonTextWriter.WriteEscapedString(String value, Boolean quote) at Newtonsoft.Json.JsonTextWriter.WritePropertyName(String name, Boolean escape) at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeDictionary(JsonWriter writer, IDictionary values, JsonDictionaryContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty) at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty) at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeList(JsonWriter writer, IEnumerable values, JsonArrayContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty) at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.Serialize(JsonWriter jsonWriter, Object value, Type objectType) at Newtonsoft.Json.JsonSerializer.SerializeInternal(JsonWriter jsonWriter, Object value, Type objectType) at EPiServer.Formatters.Internal.ExtendedNewtonsoftJsonOutputFormatter.WriteResponseBodyAsync(OutputFormatterWriteContext context, ResponseDecorator responseDecorator) at EPiServer.Formatters.Internal.ExtendedNewtonsoftJsonOutputFormatter.WriteAsync(OutputFormatterWriteContext context, ResponseDecorator responseDecorator) at EPiServer.Shell.Services.Rest.RestResultBase.ExecuteResultAsync(ActionContext context) at EPiServer.Shell.Services.Rest.RestResult.ExecuteResultAsync(ActionContext context) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.gAwaited|29_0[TFilter,TFilterAsync](ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResultExecutedContextSealed context) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext[TFilter,TFilterAsync](State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeResultFilters() --- End of stack trace from previous location --- at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|24_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync() --- End of stack trace from previous location --- at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.gAwaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope) at Microsoft.AspNetCore.Routing.EndpointMiddleware.g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger) at Microsoft.AspNetCore.Authorization.Policy.AuthorizationMiddlewareResultHandler.HandleAsync(RequestDelegate next, HttpContext context, AuthorizationPolicy policy, PolicyAuthorizationResult authorizeResult) at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context) at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context) at React.AspNet.BabelFileMiddleware.Invoke(HttpContext context) at WebMarkupMin.AspNetCore5.WebMarkupMinMiddleware.ProcessAsync(HttpContext context, Boolean useMinification, Boolean useCompression) at WebMarkupMin.AspNetCore5.WebMarkupMinMiddleware.ProcessAsync(HttpContext context, Boolean useMinification, Boolean useCompression) at WebMarkupMin.AspNetCore5.WebMarkupMinMiddlewareBase.Invoke(HttpContext context) at CorrelationId.CorrelationIdMiddleware.Invoke(HttpContext context, ICorrelationContextFactory correlationContextFactory) at EPiServer.Middleware.InitializeOnFirstRequestMiddleware.InvokeAsync(HttpContext httpContext) at EPiServer.Framework.DependencyInjection.Internal.VisitorGroupMiddleware.Invoke(HttpContext httpContext) at Microsoft.AspNetCore.Server.IIS.Core.IISHttpContextOfT`1.ProcessRequestAsync()

barteksekula commented 3 years ago

Reported in our internal tracker.

barteksekula commented 3 years ago

Microsoft fixed it as part of aspnetcore6 https://github.com/dotnet/aspnetcore/commit/0b8a066f58d63e6a8a37b073c308b30b2a60cd49

in aspnetcore5 they only allowed to control the Input threshhold: https://github.com/dotnet/aspnetcore/blob/v5.0.9/src/Mvc/Mvc.NewtonsoftJson/src/MvcNewtonsoftJsonOptions.cs#L50

in aspnetcore6 we can also control the output: https://github.com/dotnet/aspnetcore/blob/v6.0.0-preview.7.21378.6/src/Mvc/Mvc.NewtonsoftJson/src/MvcNewtonsoftJsonOptions.cs#L70

For now (until we are on aspnetcore5) customers that use newtonsoft will have to use this workaround for our stores:

var uiOptions = context.RequestServices.GetService<UIOptions>(); 
var resolver = context.RequestServices.GetService<IVirtualPathResolver>();
var syncIoFeature = context.Features.Get<IHttpBodyControlFeature>();
app.Use(async (context, next) =>
{
    var uiEditUrl = resolver.ToAbsolute(uiOptions.EditUrl.ToString()).TrimEnd('/');
    if (context.Request.Path.StartsWithSegments(uiEditUrl, StringComparison.OrdinalIgnoreCase))
    {        
        if (syncIoFeature != null)
        {
            syncIoFeature.AllowSynchronousIO = true;
        }
    }
    await next();
});