【问题标题】:MultipartFormDataStreamProvider and preserving current HttpContextMultipartFormDataStreamProvider 并保留当前的 ​​HttpContext
【发布时间】:2013-05-29 20:38:40
【问题描述】:

WebApi 的异步文件上传功能有问题。

目前我可以使用提供程序保存文件,但我想使用服务 (_myService) 来记录上传文件的文件名。在服务内部,它使用另一个服务来获取当前的 UserId。它通过使用当前的 HttpContext 来做到这一点。不幸的是,当前的 HttpContext 似乎在新任务线程中丢失了。

我尝试将 TaskScheduler.FromCurrentSynchronizationContext() 添加为任务的第二个参数,但这没有效果。不太确定这给了我什么。所以我需要某种方式将 Http 上下文传递到新线程。我将如何实现这一目标?

[ValidationFilter]
        public Task<FileUpModel> Upload([FromUri]int ReportType, [FromUri]string LocationDescription, string AdditionalInformation)
        {
            if (Request.Content.IsMimeMultipartContent())
            {
                var imagePath = HttpContext.Current.Server.MapPath("~/App_Data");

                var provider = new MyFormDataStreamProvider(imagePath);

                var task = Request.Content.ReadAsMultipartAsync(provider).ContinueWith(
                t =>
                {

                    if (t.IsFaulted || t.IsCanceled)
                        throw new HttpResponseException(HttpStatusCode.InternalServerError);

                    var fileInfo = provider.FileData.FirstOrDefault();
                    if (fileInfo == null)
                        throw new HttpResponseException(HttpStatusCode.InternalServerError);

                    // httpContext is lost here...
                    _myService.LogUploadedFile(fileInfo.LocalFileName);

                    var uploadModel = new FileUpModel { success = true };
                    return uploadModel;
                }, TaskScheduler.FromCurrentSynchronizationContext());

                return task;
            }
            else
            {
                throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotAcceptable, "This request is not properly formatted"));
            }            
        }

【问题讨论】:

    标签: asp.net-web-api httpcontext


    【解决方案1】:

    我最终发现了一个解决方法,它看起来不像我希望的那样干净。基本上,我将上下文的副本保存在一个单独的变量中,并将其传递给闭包。不确定这是否是最佳做法,但它有效!

     var currentHttpContext = HttpContext.Current;
    
            var task = Request.Content.ReadAsMultipartAsync(provider).ContinueWith(
            t =>
            {
                // Enquiry service requires access to authentication data which is retrieved via http context.
                // Not ideal but set the http context here so it available on the new thread.                    
                HttpContext.Current = currentHttpContext;
    
                if (t.IsFaulted || t.IsCanceled)
                    throw new HttpResponseException(HttpStatusCode.InternalServerError);
    
                var fileInfo = provider.FileData.FirstOrDefault();
                if (fileInfo == null)
                    throw new HttpResponseException(HttpStatusCode.InternalServerError);
    
                _myService.LogUploadedFile(fileInfo.LocalFileName);
    
                var uploadModel = new FileUpModel { success = true };
                return uploadModel;
            });
    
            return task;
    

    【讨论】:

      猜你喜欢
      • 2014-02-02
      • 1970-01-01
      • 2010-09-08
      • 2023-03-04
      • 2017-03-06
      • 1970-01-01
      • 2019-07-13
      • 2015-09-23
      相关资源
      最近更新 更多