I am fairly positive that I am creating a deadlock in my application and I am not sure how to resolve the issue. I have a few moving parts and am new to async
and await
so please bear with me.
I have a client that uploads a file as follows:
public static async Task<string> UploadToService(HttpPostedFile file, string authCode, int id)
{
var memoryStream = new MemoryStream();
file.InputStream.CopyTo(memoryStream);
var requestContent = new MultipartFormDataContent();
var fileContent = new ByteArrayContent(memoryStream.ToArray());
fileContent.Headers.ContentType = MediaTypeHeaderValue.Parse(file.ContentType);
requestContent.Add(fileContent, "file", file.FileName);
using (var httpClient = new HttpClient())
{
httpClient.BaseAddress = new Uri(BaseUrl);
httpClient.DefaultRequestHeaders.Accept.Clear();
var message =
await
httpClient.PostAsync(
string.Format("Upload?authCode={0}&id={1}", authCode, id),
requestContent);
return await message.Content.ReadAsStringAsync();
}
}
The piece receiving the file:
[HttpPost]
public Task<HttpResponseMessage> Upload(string authCode, int id)
{
var request = Request;
var provider = new CustomMultipartFormDataStreamProvider(root);
var task =
request.Content.ReadAsMultipartAsync(provider)
.ContinueWith(o =>
{
// ...
// Save file
// ...
return new HttpResponseMessage()
{
Content = new StringContent("File uploaded successfully"),
StatusCode = HttpStatusCode.OK
};
});
return task;
}
It is all kicked off with the following:
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
{
var file = HttpContext.Current.Request.Files[0];
var response = UploadToService(file, hiddenAuthCode.Value, int.Parse(hiddenId.Value));
}
}
Everything appears to be working except that the PostAsync
never recognizes that task
has been returned. I can see that the status of the await ... PostAsync ...
task is WaitingForActivation but I'm not entirely sure what that means (remember, I'm a n00b to this stuff). My file is saved to the correct location but the application never recognizes the response from my service.
If someone could point me in the right direction, it would be much appreciated.
I think the problem is that you simply call UploadToService
in a fire-and-forget manner inside Page_Load
. The request processing simply ends before this task has completed.
You should use <%@ Page Async="true" ...>
in this WebForms page and include <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
in your web.config
there.
Then use RegisterAsyncTask
, the code would look like this:
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
{
var file = HttpContext.Current.Request.Files[0];
RegisterAsyncTask(new PageAsyncTask(() => UploadToService(file,
hiddenAuthCode.Value, int.Parse(hiddenId.Value))));
}
}
On a side note, you could improve this part:
file.InputStream.CopyTo(memoryStream);
like this:
await file.InputStream.CopyToAsync(memoryStream);
and replace ContinueWith
with async/await
:
[HttpPost]
public async Task<HttpResponseMessage> Upload(string authCode, int id)
{
var request = Request;
var provider = new CustomMultipartFormDataStreamProvider(root);
await request.Content.ReadAsMultipartAsync(provider);
return new HttpResponseMessage()
{
Content = new StringContent("File uploaded successfully"),
StatusCode = HttpStatusCode.OK
};
}
Related: "Using Asynchronous Methods in ASP.NET 4.5".
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With