C# Web API MultipartSync任务没有结果
目标是将单个文件上载到我的Web服务器,然后使用multipartcontent将其存储到mssql数据库。上载文件时,客户端(WPF应用程序)中应显示进度条。下面的代码示例仅显示上传到memorystream(无数据库连接) 从客户端到服务器的连接起作用,上传到服务器端的C# Web API MultipartSync任务没有结果,c#,asynchronous,async-await,multipartform-data,webapi,C#,Asynchronous,Async Await,Multipartform Data,Webapi,目标是将单个文件上载到我的Web服务器,然后使用multipartcontent将其存储到mssql数据库。上载文件时,客户端(WPF应用程序)中应显示进度条。下面的代码示例仅显示上传到memorystream(无数据库连接) 从客户端到服务器的连接起作用,上传到服务器端的MemoryStream起作用,接收到客户端的百分比起作用(我的示例代码中的ContinueWith部分)。问题是,客户端没有收到最终的CreateResponse请求-例如超时或连接丢失,我不确定,因为我没有收到错误/异常。
MemoryStream
起作用,接收到客户端的百分比起作用(我的示例代码中的ContinueWith
部分)。问题是,客户端没有收到最终的CreateResponse
请求-例如超时或连接丢失,我不确定,因为我没有收到错误/异常。客户端从未收到任务最终结果
WebApi:
public class AttachmentsController : ApiController
{
[HttpPost]
[Route("api/Attachments/Upload")]
public async Task<HttpResponseMessage> Upload()
{
if (!Request.Content.IsMimeMultipartContent())
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
try
{
AttachmentUpload _resultAttachmentUpload = null;
var _provider = new InMemoryMultipartFormDataStreamProvider();
await Request.Content.ReadAsMultipartAsync(_provider)
.ContinueWith(t =>
{
if (t.IsFaulted || t.IsCanceled)
{
throw new HttpResponseException(
HttpStatusCode.InternalServerError);
}
return new AttachmentUpload()
{
FileName = _provider.Files[0].Headers.ContentDisposition
.FileName.Trim('\"'),
Size = _provider.Files[0].ReadAsStringAsync().Result
.Length / 1024
};
});
return Request.CreateResponse<AttachmentUpload>(HttpStatusCode.Accepted,
_resultAttachmentUpload);
}
catch (Exception e)
{
return Request.CreateErrorResponse(HttpStatusCode.InternalServerError,
e.ToString());
}
}
}
公共类附件控制器:ApiController
{
[HttpPost]
[路由(“api/附件/上传”)]
公共异步任务上载()
{
如果(!Request.Content.IsMimeMultipartContent())
抛出新的HttpResponseException(HttpStatusCode.UnsupportedMediaType);
尝试
{
AttachmentUpload _resultAttachmentUpload=null;
var_provider=新的InMemoryMultipartFormDataStreamProvider();
wait Request.Content.ReadAsMultipartAsync(\u provider)
.ContinueWith(t=>
{
如果(t.IsFaulted | | t.IsCanceled)
{
抛出新的HttpResponseException(
HttpStatusCode.InternalServerError);
}
返回新的AttachmentUpload()
{
FileName=\u provider.Files[0].Headers.ContentDisposition
.FileName.Trim(“\”),
大小=_provider.Files[0]。ReadAsStringAsync().Result
.长度/1024
};
});
返回请求.CreateResponse(HttpStatusCode.Accepted,
_结果附件上传);
}
捕获(例外e)
{
返回请求.CreateErrorResponse(HttpStatusCode.InternalServerError,
e、 ToString());
}
}
}
WPF Client UploadService.cs:
private async Task<Attachment> UploadAttachment(AttachmentUpload uploadData,
string filePath)
{
try
{
var _encoding = Encoding.UTF8;
MultipartFormDataContent _multipartFormDataContent =
new MultipartFormDataContent();
_multipartFormDataContent.Add(new StreamContent(new MemoryStream(
File.ReadAllBytes(filePath))), uploadData.FileName, uploadData.FileName);
_multipartFormDataContent.Add(new StringContent(uploadData.Id.ToString()),
"AttachmentId", "AttachmentId");
_multipartFormDataContent.Add(new StringContent(
uploadData.Upload.ToString(CultureInfo.CurrentCulture)), "AttachmentUpload",
"AttachmentUpload");
_multipartFormDataContent.Add(new StringContent(
uploadData.DocumentId.ToString()), "DocumentId", "DocumentId");
_multipartFormDataContent.Add(new StringContent(
uploadData.User, _encoding), "User", "User");
//ProgressMessageHandler is instantiate in ctor to show progressbar
var _client = new HttpClient(ProgressMessageHandler);
_client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("multipart/form-data"));
_client.Timeout = TimeSpan.FromMinutes(5);
var _requestUri = new Uri(BaseAddress + "api/Attachments/Upload");
var _httpRequestTask = await _client.PostAsync(_requestUri,
_multipartFormDataContent)
.ContinueWith<AttachmentUpload>(request =>
{
var _httpResponse = request.Result;
if (!_httpResponse.IsSuccessStatusCode)
{
throw new Exception();
}
var _response = _httpResponse.Content.ReadAsStringAsync();
AttachmentUpload _upload =
JsonConvert.DeserializeObject<AttachmentUpload>(_response.Result);
return _upload;
});
var _resultAttachment = _httpRequestTask;
return new Attachment()
{
Id = _resultAttachment.Id,
FileName = _resultAttachment.FileName,
Comment = _resultAttachment.Comment,
Upload = _resultAttachment.Upload,
};
}
catch (Exception e)
{
//Handle exceptions
//file not found, access denied, no internet connection etc etc
var tmp = e;
throw e;
}
}
专用异步任务上传附件(AttachmentUploadData,
字符串(文件路径)
{
尝试
{
var_encoding=encoding.UTF8;
MultipartFormDataContent\u MultipartFormDataContent=
新的MultipartFormDataContent();
_multipartFormDataContent.Add(新的StreamContent(新的MemoryStream(
File.ReadAllBytes(filePath))),uploadData.FileName,uploadData.FileName);
_multipartFormDataContent.Add(新的StringContent(uploadData.Id.ToString()),
“AttachmentId”、“AttachmentId”);
_multipartFormDataContent.Add(新的StringContent(
uploadData.Upload.ToString(CultureInfo.CurrentCulture)),“AttachmentUpload”,
“附件上传”);
_multipartFormDataContent.Add(新的StringContent(
uploadData.DocumentId.ToString(),“DocumentId”,“DocumentId”);
_multipartFormDataContent.Add(新的StringContent(
uploadData.User,_编码),“User”,“User”);
//ProgressMessageHandler在ctor中实例化以显示progressbar
var_client=新的HttpClient(ProgressMessageHandler);
_client.DefaultRequestHeaders.Accept.Add(
新的MediaTypeWithQualityHeaderValue(“多部分/表单数据”);
_client.Timeout=TimeSpan.frommins(5);
var_requestUri=新Uri(BaseAddress+“api/附件/上传”);
var\u httpRequestTask=wait\u client.PostAsync(\u requestUri,
_multipartFormDataContent)
.ContinueWith(请求=>
{
var_httpResponse=request.Result;
如果(!\u httpResponse.IsSuccessStatusCode)
{
抛出新异常();
}
var_response=_httpResponse.Content.ReadAsStringAsync();
附件上传\u上传=
JsonConvert.DeserializeObject(_response.Result);
返回上传;
});
var\u resultAttachment=\u httpRequestTask;
返回新附件()
{
Id=\u resultAttachment.Id,
FileName=\u resultAttachment.FileName,
Comment=\u resultAttachment.Comment,
Upload=\u resultAttachment.Upload,
};
}
捕获(例外e)
{
//处理异常
//未找到文件、访问被拒绝、没有internet连接等
var tmp=e;
投掷e;
}
}
程序缺少atvar\u httpRequestTask=wait\u client.PostAsync(…)
。
调试器从未到达行var\u resultAttachment=\u httpRequestTask;
非常感谢您的帮助。首先,不要将
wait
和ContinueWith
混为一谈,async
/wait
的引入有效地使ContinueWith
过时
var\u resultAttachment=\u httpRequestTask;
从未命中的原因是您创建了死锁
WPF有一个同步上下文,确保在UI线程上继续
在AttachmentUpload\u upload=JsonConvert.DeserializeObject(\u response.Result);
行中,\u response.Result
是一个阻塞调用;它阻塞当前线程,直到\u response
引用的任务完成
生成任务
的ReadAsStringAsync
方法将在异步工作完成后尝试恢复,WPF同步上下文将强制其使用UI线程,该线程已被\u response.Result
阻止,因此出现死锁
要解决此问题,请将wait
关键字用于var _httpResponse = await _client.PostAsync(_requestUri, _multipartFormDataContent);
if (!_httpResponse.IsSuccessStatusCode)
{
throw new Exception();
}
var _response = await _httpResponse.Content.ReadAsStringAsync();
var _resultAttachment = JsonConvert.DeserializeObject<AttachmentUpload>(_response);