Returning Void in Async method from WEB API Controller
Asked Answered
P

3

8

I have this async method inside ASP.NET MVC 4 WEB API Controller that I got from this blog: http://www.strathweb.com/2012/04/html5-drag-and-drop-asynchronous-multi-file-upload-with-asp-net-webapi/

  public async Task<IList<RecivedFile>> Post()
    {
        List<RecivedFile> result = new List<RecivedFile>();
        if (Request.Content.IsMimeMultipartContent())
        {
            try
            {
                MultipartFormDataStreamProvider stream = new MultipartFormDataStreamProvider(HostingEnvironment.MapPath("~/USER-UPLOADS"));

                IEnumerable<HttpContent> bodyparts = await Request.Content.ReadAsMultipartAsync(stream);
                IDictionary<string, string> bodyPartFiles = stream.BodyPartFileNames;
                IList<string> newFiles = new List<string>();

                foreach (var item in bodyPartFiles)
                {
                    var newName = string.Empty;
                    var file = new FileInfo(item.Value);

                    if (item.Key.Contains("\""))
                        newName = Path.Combine(file.Directory.ToString(), item.Key.Substring(1, item.Key.Length - 2));
                    else
                        newName = Path.Combine(file.Directory.ToString(), item.Key);

                    File.Move(file.FullName, newName);
                    newFiles.Add(newName);
                }

                var uploadedFiles = newFiles.Select(i =>
                {
                    var fi = new FileInfo(i);
                    return new RecivedFile(fi.Name, fi.FullName, fi.Length);
                }).ToList();

                result.AddRange(uploadedFiles);
            }
            catch (Exception e)
            {
            }
        }
        return result;
    }

My question is why exactly does this method have a return type of Task? It is not clear "where to" or "to whom" it returns this task? It's like there is no one that waits for/receives the returned object.

I wonder what will be the implications if I return void like this:

EDIT:

I have tried the code below and it completely breaks the program. it's like the runtime looses the reference to the code, the code itself doesn't finish running.

    public async void Post()
    {
        List<RecivedFile> result = new List<RecivedFile>();
        if (Request.Content.IsMimeMultipartContent())
        {
            try
            {
                MultipartFormDataStreamProvider stream = new MultipartFormDataStreamProvider(HostingEnvironment.MapPath("~/USER-UPLOADS"));

                IEnumerable<HttpContent> bodyparts = await Request.Content.ReadAsMultipartAsync(stream);
                IDictionary<string, string> bodyPartFiles = stream.BodyPartFileNames;
                IList<string> newFiles = new List<string>();

                foreach (var item in bodyPartFiles)
                {
                    var newName = string.Empty;
                    var file = new FileInfo(item.Value);

                    if (item.Key.Contains("\""))
                        newName = Path.Combine(file.Directory.ToString(), item.Key.Substring(1, item.Key.Length - 2));
                    else
                        newName = Path.Combine(file.Directory.ToString(), item.Key);

                    File.Move(file.FullName, newName);
                    newFiles.Add(newName);
                }

            }
            catch (Exception e)
            {
            }
        }

    }
Placeman answered 11/8, 2012 at 13:33 Comment(0)
E
7

The ASP.NET runtime waits for it. You may find this video useful.

Most examples for async assume a UI context. ASP.NET also provides a context, but it's a "request" context - one for each HTTP request. My async/await post gives an overview of this "context", and the async/await FAQ goes into much more detail.

Ethiopic answered 11/8, 2012 at 15:24 Comment(3)
So the conclusion is to never return void in async methods when used in ASP.NETPlaceman
There are a handful of situations in ASP.NET 4.5 where you can use an async void method - the runtime will detect it and react appropriately. But as a general rule, it's best to use async Task unless you really have to do async void.Ethiopic
since async void is essentially "fire and forget" there very rarely is a reason to do that. One example is the page_load in the new Web Forms - protected async void Page_Load(object sender, EventArgs e)Cataplexy
S
0

With return type void you don't wait for an object to return.. You wait for an operation to finish. You wait for your Task to finish.

Storyteller answered 11/8, 2012 at 13:35 Comment(1)
Not sure to whom you refer by saying "you" ("you don't wait"). I don't want to wait for anything. The point here that it is used in WEB API and I can't understand what exactly do you want me to wait for?Placeman
C
0

If you return void, you will be returning 204 "No Content" Response message immediately regardless of the completion status of your asynchronous operation. This is done by the help of VoidResultConverter.

Note: On RC, you will see that it returns 200 "OK" response but with the RTM, it will return 204 "No Content" response.

Canea answered 11/8, 2012 at 15:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.