MultipartFormDataStreamStreamProvider并保留当前的HttpContext [英] MultipartFormDataStreamProvider and preserving current HttpContext

查看:85
本文介绍了MultipartFormDataStreamStreamProvider并保留当前的HttpContext的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对WebApi的异步文件上传功能有疑问.

I have a problem with the async file uploading feature of WebApi.

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

Currently I am able to save the file using the provider, but I then want to use a service (_myService) to log the filename of the file uploaded. Inside the service, it uses another service to get the current UserId. It does this by using the current HttpContext. Unfortunately the current HttpContext seems to be lost within the new task thread.

我试图将TaskScheduler.FromCurrentSynchronizationContext()添加为任务的第二个参数,但这没有任何效果.不太确定这能给我带来什么.因此,我需要一些将Http上下文传递到新线程的方法.我将如何实现呢?

I tried to add TaskScheduler.FromCurrentSynchronizationContext() as the 2nd parameter of the task but this had no effect. Not really sure what that gives me. So I need some way of getting the Http context across to the new thread. How would I achieve this?

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

推荐答案

我最终发现了一个解决方法,它看起来不像我想要的那样干净.基本上,我将上下文的副本保存在单独的变量中,并将其传递给闭包.不知道这是否是最佳实践,但它可以正常工作!

I discovered a work around in the end, it doesn't look as clean as I would have liked. Basically, I keep a copy of the context in a separate variable and pass this into the closure. Not sure if this is best practise or not but it works!

 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;

这篇关于MultipartFormDataStreamStreamProvider并保留当前的HttpContext的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆