ASP.NET Core:不允许同步操作。调用WriteAsync或将AllowSynchronousIO设置为true

时间:2017-12-10 01:57:46

标签: asp.net-mvc

ASP.NET核心服务器AllowSynchronousIO设置为false

        new WebHostBuilder()
        .UseKestrel(options =>
        {
            options.AllowSynchronousIO = false;
        })

在动作中,它输出一个JsonResult

    public async Task<IActionResult> SanityCheck()
    {
        Dictionary<string, string> dic = await GetDic();

        return this.Json(dic);
    }

它以异常结束

  

System.InvalidOperationException:同步操作是   不允许。调用WriteAsync或将AllowSynchronousIO设置为true。

我不能用AllowSynchronousIO=false返回JsonResult吗?

最好的问候

5 个答案:

答案 0 :(得分:4)

我的单元测试中有这个问题。我必须将TestServer更新为AlloSynchronousIO

Server = new TestServer(new WebHostBuilder().UseStartup<Startup>());
Server.AllowSynchronousIO = true;

答案 1 :(得分:2)

您可能遇到以下问题:https://github.com/aspnet/AspNetCore/issues/8302

您可以在此处找到更多信息:https://github.com/aspnet/AspNetCore/issues/7644

直到解决此问题的变通办法是允许syncIO。将其放在Startup.cs中。如果您使用的是IIS,则为IISServerOptions。

 public void ConfigureServices(IServiceCollection services)
    {
        services.Configure<KestrelServerOptions>(options =>
        {
            options.AllowSynchronousIO = true;
        });
    }

答案 2 :(得分:1)

基于 Mark Lagendijkanswer,我以具有属性的声明方式应用了该逻辑:

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

只需在操作方法或整个控制器上使用它即可启用它:

[AllowSynchronousIO]
public IActionResult DownloadSynchronous()
{
    return Something();
}

答案 3 :(得分:0)

我不确定您的要求是什么或GetDic()做什么,但是在GetDic()不执行任何同步IO的情况下,以下代码绝对可以正常工作:

public async Task<IActionResult> SanityCheck()
{
    Dictionary<string, string> dic = await GetDic();

    return this.Ok(dic);
}

如果您仍然想将dic序列化为JSON,则应执行以下代码:

public async Task<IActionResult> SanityCheck()
{
    Dictionary<string, string> dic = await GetDic();
    string json = JsonConvert.SerializeObject(dic);

    return this.Ok(json);
}

请注意,这最后一段代码以text/plain而不是application/json的形式返回结果。

我也在ASP.NET Core 2.2下进行了测试。

答案 4 :(得分:0)

这段代码对我有用,异步读取:

public override async void OnActionExecuting(ActionExecutingContext filterContext)
{
    string content = "";
    var request = filterContext.HttpContext.Request;
    try
    {
        request.EnableBuffering();
        request.Body.Position = 0;
        using (StreamReader reader = new StreamReader(request.Body, Encoding.UTF8,true,1024,true))
        {
            content = await reader.ReadToEndAsync();
        }
    }
    finally
    {
        request.Body.Position = 0;
    }
}