ASP.NET Core : Synchronous operations are disallowed. Call WriteAsync or set AllowSynchronousIO to true instead
You might have the following problem: https://github.com/aspnet/AspNetCore/issues/8302
And you can find more info here: https://github.com/aspnet/AspNetCore/issues/7644
A workaround until the issue is being solved is to allow Synchronous IO. Put this in Startup.cs for either Kestrel or IIS:
public void ConfigureServices(IServiceCollection services)
{
// If using Kestrel:
services.Configure<KestrelServerOptions>(options =>
{
options.AllowSynchronousIO = true;
});
// If using IIS:
services.Configure<IISServerOptions>(options =>
{
options.AllowSynchronousIO = true;
});
}
I had this issue with my unit tests. I had to update my TestServer to AlloSynchronousIO
Server = new TestServer(new WebHostBuilder().UseStartup<Startup>());
Server.AllowSynchronousIO = true;
When the exception is thrown in code you cannot control, and you have no other choice than to enable AllowSynchronousIO
, it is best to enable it for specific requests, instead of globally.
In the GitHub issue announcing this feature, the following workaround is suggested:
var syncIOFeature = HttpContext.Features.Get<IHttpBodyControlFeature>();
if (syncIOFeature != null)
{
syncIOFeature.AllowSynchronousIO = true;
}
You can create a simple middleware function to apply this to specific requests:
app.Use(async (context, next) =>
{
if (context.Request.Path.StartsWithSegments("/some-endpoint-that-needs-sync-io"))
{
var syncIoFeature = context.Features.Get<IHttpBodyControlFeature>();
if (syncIoFeature != null)
{
syncIoFeature.AllowSynchronousIO = true;
}
}
await next();
})
Based on Mark Lagendijk's answer, i applied that logic on a declarative way with an attribute:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class AllowSynchronousIOAttribute : ActionFilterAttribute
{
public AllowSynchronousIOAttribute()
{
}
public override void OnResultExecuting(ResultExecutingContext context)
{
var syncIOFeature = context.HttpContext.Features.Get<IHttpBodyControlFeature>();
if (syncIOFeature != null)
{
syncIOFeature.AllowSynchronousIO = true;
}
}
}
Just use it on an action method or an entire controller to enable it:
[AllowSynchronousIO]
public IActionResult DownloadSynchronous()
{
return Something();
}