ASP.NET Web API 2-ReadaMultipartAsync替代方案/如何

ASP.NET Web API 2-ReadaMultipartAsync替代方案/如何,asp.net,asp.net-web-api,async-await,Asp.net,Asp.net Web Api,Async Await,我正在使用Web API 2.2接收包含表单数据和文件的HTTP post,我正在执行以下操作: 同步版本: [HttpPost] public IHttpActionResult CreateTicket() { string root = HttpContext.Current.Server.MapPath("~/UserFiles/Temp/"); var provider = new MultipartFormDataStreamProvider(root);

我正在使用Web API 2.2接收包含表单数据和文件的HTTP post,我正在执行以下操作:

同步版本:

[HttpPost]
public IHttpActionResult CreateTicket()
{
    string root = HttpContext.Current.Server.MapPath("~/UserFiles/Temp/");
    var provider = new MultipartFormDataStreamProvider(root);

    // Timeouts
    Request.Content.ReadAsMultipartAsync(provider).Wait(TimeSpan.FromSeconds(20));
    ...
} 
[HttpPost]
public async Task<HttpResponseMessage> CreateTicket()
{
    string root = HttpContext.Current.Server.MapPath("~/UserFiles/Temp/");
    var provider = new MultipartFormDataStreamProvider(root);

    // Works
    await Request.Content.ReadAsMultipartAsync(provider);
    ...
    // Error because: HttpContext.Current == null
} 
异步版本:

[HttpPost]
public IHttpActionResult CreateTicket()
{
    string root = HttpContext.Current.Server.MapPath("~/UserFiles/Temp/");
    var provider = new MultipartFormDataStreamProvider(root);

    // Timeouts
    Request.Content.ReadAsMultipartAsync(provider).Wait(TimeSpan.FromSeconds(20));
    ...
} 
[HttpPost]
public async Task<HttpResponseMessage> CreateTicket()
{
    string root = HttpContext.Current.Server.MapPath("~/UserFiles/Temp/");
    var provider = new MultipartFormDataStreamProvider(root);

    // Works
    await Request.Content.ReadAsMultipartAsync(provider);
    ...
    // Error because: HttpContext.Current == null
} 
[HttpPost]
公共异步任务CreateTicket()
{
字符串root=HttpContext.Current.Server.MapPath(“~/UserFiles/Temp/”);
var provider=新的MultipartFormDataStreamProvider(根);
//工作
wait Request.Content.ReadAsMultipartAsync(提供程序);
...
//错误原因:HttpContext.Current==null
} 
此代码的两个版本都在IIS 10中工作,但在生产(IIS 8.5)中失败。。第一个版本超时,第二个版本正常,但是HttpContext.Current不可用,这使得我的代码的其他部分失败

如何使上载同步(首选)或异步代码具有可用的HttpContext.Current

更新:

[HttpPost]
public IHttpActionResult CreateTicket()
{
    string root = HttpContext.Current.Server.MapPath("~/UserFiles/Temp/");
    var provider = new MultipartFormDataStreamProvider(root);

    // Timeouts
    Request.Content.ReadAsMultipartAsync(provider).Wait(TimeSpan.FromSeconds(20));
    ...
} 
[HttpPost]
public async Task<HttpResponseMessage> CreateTicket()
{
    string root = HttpContext.Current.Server.MapPath("~/UserFiles/Temp/");
    var provider = new MultipartFormDataStreamProvider(root);

    // Works
    await Request.Content.ReadAsMultipartAsync(provider);
    ...
    // Error because: HttpContext.Current == null
} 
刚刚发现问题(在第二个代码片段中)只有在应用程序的web.config中没有以下内容时才会发生:

<httpRuntime targetFramework="4.6.1" />
<httpRuntime targetFramework="4.6.1" />


仍在调查副作用,看看我是否可以安全地应用它,或者是否需要更改代码。

要在
ASP.NET Core
中检索文件,请尝试使用而不是
HttpContext
——有关通过
DI配置和注入它的更多详细信息,请参阅文档

如果这是上传多个文件和接收其他数据的
POST
控制器操作-您可以这样做下面我使用
查看
进行演示,但数据可以作为API POST请求从任何地方移动

查看

@model MyNamespace.Models.UploadModel

<form asp-controller="MyController" asp-action="Upload" enctype="multipart/form-data" method="post">
     <input asp-for="OtherProperty">
     <input name="Files" multiple type="file">
     <button type="submit" class="btn btn-success">Upload</button>
</form>
控制器

[HttpGet]
public IActionResult Upload()
{
    return View(new UploadModel());
}

[HttpPost]
public async Task<IActionResult> Index(UploadModel model)
{
    var otherProperty = model.OtherProperty;
    var files = new Dictionary<string, string>();

    foreach (IFormFile file in model.Files)
    {
        using (var reader = new StreamReader(file.OpenReadStream()))
        {
            string content = await reader.ReadToEndAsync();
            files.Add(file.Name, content);

            // Available file properties: 

            // file.FileName
            // file.ContentDisposition
            // file.ContentType
            // file.Headers
            // file.Length
            // file.Name

            // You can copy file to other stream if needed:
            // file.CopyTo(new MemoryStream()...);
        }
    }
}
[HttpGet]
公共IActionResult上载()
{
返回视图(新上载模型());
}
[HttpPost]
公共异步任务索引(UploadModel)
{
var otherProperty=model.otherProperty;
var files=newdictionary();
foreach(model.Files中的文件)
{
使用(var reader=newstreamreader(file.OpenReadStream()))
{
string content=wait reader.ReadToEndAsync();
files.Add(file.Name,content);
//可用文件属性:
//file.FileName
//file.ContentDisposition
//file.ContentType
//文件头
//文件长度
//文件名
//如果需要,您可以将文件复制到其他流:
//CopyTo(newmemorystream()…);
}
}
}

通过创建一个小应用程序并尝试复制它,我终于找到了答案。正如德米特里和保罗所指出的,这应该是可行的。但是,它应该适用于任何新项目,在我的情况下,该项目已经有10年的历史,并且有很多遗留配置

TL;DR:async
/
await
关键字工作不正常(调用
await
后,
HttpContext.Current
将为空)。如果web.config中不存在此设置,则:

<httpRuntime targetFramework="4.6.1" />
<httpRuntime targetFramework="4.6.1" />

这是一系列设置的快捷方式,包括这个(我在这里关心的):


作为参考,它说:

启用新的等待友好型异步管道 在4.5中引入。我们的许多同步原语在早期 ASP.NET版本有一些不好的行为,例如在公共服务器上使用锁 对象或违反API约定。事实上,ASP.NET4 SynchronizationContext.Post的实现是一个阻塞 同步呼叫!新的异步管道力求更加灵活 高效,同时遵守其API的预期合同。 新的管道还对数据执行少量的错误检查 代表开发人员,例如检测对 异步void方法

某些功能(如WebSocket)需要设置此开关。 重要的是,async/await的行为在ASP.NET中没有定义 除非已设置此开关。(请记住:设置
也足够了。)

如果该设置根本不存在,则假定版本4.0,并在“怪癖”模式下工作:

如果Web.config中没有属性,我们假设应用程序需要4.0怪癖行为


每次你打电话给
等待
处理
任务
/
任务
,你都是在自找麻烦。你还用那种方法干什么?任何
配置等待(false)
?我很惊讶
HttpContext。当前的
null
@PauloMorgado我没有做任何不寻常的事情,也没有使用
configurewait
。在
wait
之后是
HttpContext.Current==null