Wesley
Wesley

Reputation: 5621

ASYNC error on WebApi Download

I have the following code, used to download multiple files, create a zip file, and return the file to the user:

//In a WebAPI GET Handler
public async Task<HttpResponseMessage> Get(string id)
{
    try
    {
        var urlList = CacheDictionary<String, List<String>>.Instance[id];
        var helper = new Helper();
        var zipFile = await helper.CreateZipFormUrls(urlList);

        var response = new HttpResponseMessage(HttpStatusCode.OK);
        var stream = new MemoryStream();
        zipFile.Save(stream);
        response.Content = new ByteArrayContent(stream.ToArray());

        response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
        response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/zip");
        response.Content.Headers.ContentLength = stream.Length;
        response.Content.Headers.ContentDisposition.FileName = "download.zip";

        return response;
    }
    catch (Exception)
    {
        return Request.CreateResponse(HttpStatusCode.BadRequest);
    }
}

//In a Helper Class
public async Task<ZipFile> CreateZipFromUrls(List<string> urlList)
{
    using (var zip = new ZipFile())
    {
        var files = await ReturnFileData(urlList);
        foreach (var file in files)
        {
            var e = zip.AddEntry(GetFileNameFromUrlString(file.Key), file.Value);
        }

        return zip;
    }
}

static Task<Dictionary<string, byte[]>> ReturnFileData(IEnumerable<string> urls)
{
    Dictionary<Uri, Task<byte[]>> dictionary;
    using (var client = new WebClient())
    {
        dictionary = urls.Select(url => new Uri(url)).ToDictionary(
            uri => uri, uri => client.DownloadDataTaskAsync(uri));
        await Task.WhenAll(dictionary.Values);
    }

    return dictionary.ToDictionary(pair => Path.GetFileName(pair.Key.ToString()),
         pair => pair.Value.Result);
}

private string GetFileNameFromUrlString(string url)
{
    var uri = new Uri(url);
    return System.IO.Path.GetFileName(uri.LocalPath);
}

I always get:

An asynchronous module or handler completed while an asynchronous operation was still pending

And cannot reach any breakpoints after the download method is called. What am I doing wrong? Where do I look?

Upvotes: 0

Views: 268

Answers (1)

hatcyl
hatcyl

Reputation: 2352

Try await on this

dictionary = urls.Select(url => new Uri(url)).ToDictionary(
            uri => uri, uri => client.DownloadDataTaskAsync(uri));

The problem might be that

client.DownloadDataTaskAsync(uri)); 

is probably still running when the rest of your code is done.

Upvotes: 1

Related Questions