【问题标题】:MultipartStreamProvider loses HttpContext after async workMultipartStreamProvider 在异步工作后丢失 HttpContext
【发布时间】:2017-02-03 23:47:51
【问题描述】:

我已经实现了 MultipartStreamProvider 的自定义子类,以便将上传的文件数据写入自定义流。写入流后,HttpContext 有时会丢失。下面的代码是演示问题的简化重现。如果自定义流实际上没有在 WriteAsync 中执行任何异步工作(即,如果它保持在同一个线程上),那么一切都会按您的预期工作。但是,一旦我们将一些实际的异步工作引入到 WriteAsync(这里由 Task.Delay 模拟),那么 HttpContext(通常)就会丢失。是我做错了什么,还是 Web API 框架中的错误?

public class TestApiController : ApiController
{
    public class CustomMultipartStreamProvider : MultipartStreamProvider
    {
        private readonly List<string> _fileNames = new List<string>();
        private readonly List<Stream> _fileStreams = new List<Stream>();

        public CustomMultipartStreamProvider()
        {
        }

        public override Stream GetStream(HttpContent parent, HttpContentHeaders headers)
        {
            string filename;
            if (IsFileContent(headers, out filename))
            {
                var stream = new CustomStream();
                _fileStreams.Add(stream);
                _fileNames.Add(filename);

                return stream;
            }

            return new MemoryStream();
        }

        private static bool IsFileContent(HttpContentHeaders headers, out string filename)
        {
            var contentDisposition = headers.ContentDisposition;
            if (contentDisposition == null)
            {
                filename = null;
                return false;
            }

            filename = UnquoteToken(contentDisposition.FileName);

            return !string.IsNullOrEmpty(filename);
        }

        private static string UnquoteToken(string token)
        {
            if (string.IsNullOrWhiteSpace(token))
                return token;

            if (token.StartsWith("\"", StringComparison.Ordinal) && token.EndsWith("\"", StringComparison.Ordinal) && token.Length > 1)
                return token.Substring(1, token.Length - 2);

            return token;
        }
    }

    class CustomStream : MemoryStream
    {
        public override async Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
        {
            await Task.Delay(100, cancellationToken); // simulate async work (if this line is commented out, everything works correctly)
            await base.WriteAsync(buffer, offset, count, cancellationToken);
        }
    }

    [Route("api/test/multipart")]
    public async Task<string> PutMultiPart()
    {
        // Check if the request contains multipart/mixed content
        if (!Request.Content.IsMimeMultipartContent("mixed"))
            throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);

        // Read the multipart data
        var multipartStreamProvider = new CustomMultipartStreamProvider();
        await Request.Content.ReadAsMultipartAsync(multipartStreamProvider);

        if (HttpContext.Current != null)
        {
            return "good";
        }
        else
        {
            return "bad";
        }
    }
}

出于测试目的,我发送的请求本质上是这样的:

Content-Type: multipart/mixed; boundary=boundary42
--boundary42 
Content-Type: application/json

{
  Description: "test file"
}
--boundary42
Content-Type: application/octet-stream 
Content-Disposition: inline; filename=hello.txt

Hello world.
--boundary42--

【问题讨论】:

  • @StephenCleary 感谢您的提示-原来它已设置为 4.0。但是,更改为 4.5 似乎没有帮助...
  • @jr75:您实际上是在 ASP.NET 4.5 或更高版本上运行吗?您是否安装了Microsoft.Bcl.Async NuGet 包?
  • @StephenCleary 我很确定我们正在运行 ASP.NET 4.6。该项目的目标是 .NET 4.6.1,我们没有使用 Bcl.Async,并且 async/await 似乎确实在 ASP.NET 中对我们普遍有效——这只是我遇到问题的一种情况。

标签: asp.net asp.net-web-api async-await asp.net-web-api2


【解决方案1】:

事实证明@StephenCleary 的建议是正确的:将 web.config 中的 targetFramework 设置为 >= 4.5 可以解决问题,但是,您必须设置 right targetFramework 属性。我第一次尝试换行

&lt;compilation debug="true" targetFramework="4.0" /&gt;

&lt;compilation debug="true" targetFramework="4.5" /&gt;

这没有任何效果。需要更新的是 httpRuntime 元素:

&lt;httpRuntime targetFramework="4.5" /&gt;

【讨论】:

    猜你喜欢
    • 2015-09-01
    • 1970-01-01
    • 2012-10-31
    • 1970-01-01
    • 2017-12-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多