This article is only applicable for CMS 12, Commerce Connect 14.
Symptoms
The exception System.lnvalidOperationException happens sporadically when working in CMS or Commerce Connect UI. It often occurs when an editor tries to expand a content/product node with lots of children items.
Sample error stack trace:
System.InvalidOperationException: Synchronous operations are disallowed, Call WriteAsync or set AllowSynchronouslO to true instead.
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpResponseStream.Write(Byte[] buffer, Int32 offset, Int32 count)
at System.IO.Compression.DeflateStream.WriteDeflaterOutput()
at System.IO.Compression.DeflateStream.WriteCore(ReadOnlySpan`1 buffer)
at System.IO.Compression.DeflateStream.Write(Byte[] buffer, Int32 offset, Int32 count)
at MicrosoftAspNetCore.ResponseCompression.ResponseCompressicnBody.Write(Byte[] buffer, Int32 offset, Int32 count)
at MicrosoftAspNetCore.WebUtilities.HttpResponseStreamWrfter.Write(String value)
at NewtonsoftJson.JsonTextWriter.WritePropertyName(String name, Boolean escape)
Explanation
In some cases, the size of data is large and Newtonsoft.Json has to stream the serialized data to the client-side by using a StreamWriter. That requires the hosting service (Kestrel) to allow synchronous read/write operations.
Due to a bug of NetCore, AllowSynchronousIO is set to "false" by default from NetCore 3 (see reference).
Fix and mitigation
- Replace Newtonsoft.Json implementation with System.Text.Json serialization. The CMS will use System.Text.Json serialization by default.
- Update CMS Core and Newtonsoft.Json to latest version.
- Enable AllowSynchronousIO in code:
Option 1: Program.Main() entry-point
public static void Main(string[] args) => Host.CreateDefaultBuilder(args)
.ConfigureCmsDefaults()
.ConfigureWebHostDefaults(webBuilder => webBuilder
.UseKestrel(options => options.AllowSynchronousIO = true)
.UseStartup<Startup>())
.Build().Run();
Option 2: Startup.ConfigureServices() method
services.Configure<KestrelServerOptions>(options =>
{
options.AllowSynchronousIO = true;
});
Remarks
- Microsoft warns about the possibility of threading starvation issue. Therefore, only use the configuration when the error appears frequently or constantly.
- When enabled, avoid or minimize the usage of MemoryStream and other Stream features, or ensure it's used with control. Utilize ReadAsync and WriteAsync for custom codes.
- Kestrel Synchronous IO reference: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/servers/kestrel/options?view=aspnetcore-7.0#other-options
Please sign in to leave a comment.