Web API 2 download file using async Task<IHttpActionResult>

给你一囗甜甜゛ 提交于 2019-11-30 03:44:44
Kiran Challa

Right, for your above scenario the action does not need to return an async action result. Here I am creating a custom IHttpActionResult. You can check my comments in the below code here.

public IHttpActionResult GetFileAsync(int fileId)
{
    // NOTE: If there was any other 'async' stuff here, then you would need to return
    // a Task<IHttpActionResult>, but for this simple case you need not.

    return new FileActionResult(fileId);
}

public class FileActionResult : IHttpActionResult
{
    public FileActionResult(int fileId)
    {
        this.FileId = fileId;
    }

    public int FileId { get; private set; }

    public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
    {
        HttpResponseMessage response = new HttpResponseMessage();
        response.Content = new StreamContent(File.OpenRead(@"<base path>" + FileId));
        response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");

        // NOTE: Here I am just setting the result on the Task and not really doing any async stuff. 
        // But let's say you do stuff like contacting a File hosting service to get the file, then you would do 'async' stuff here.

        return Task.FromResult(response);
    }
}

Methods are asynchronous if return a Task object, not because are decorated with async keyword. async is only a syntactical sugar to replace this syntax what can get rather complex when there are more tasks combined or more continuations:

public Task<int> ExampleMethodAsync()
{
    var httpClient = new HttpClient();

    var task = httpClient.GetStringAsync("http://msdn.microsoft.com")
        .ContinueWith(previousTask =>
        {
            ResultsTextBox.Text += "Preparing to finish ExampleMethodAsync.\n";

            int exampleInt = previousTask.Result.Length;

            return exampleInt;
        });

    return task;
}

Original sample with async: http://msdn.microsoft.com/en-us/library/hh156513.aspx

async always requires await, this is enforced by compiler.

Both implementations are asynchroous, the only difference is that async+await replaces expands the ContinueWith into "synchronous" code.

Returning Task from controller methods what do IO (99% of cases I estimate) is important because the runtime can suspend and reuse the request thread to serve other requests while the IO operation is in progress. This lowers the chances of running out of thread pool threads. Here's an article on the topic: http://www.asp.net/mvc/overview/performance/using-asynchronous-methods-in-aspnet-mvc-4

So the answer to your question "Does the above needs to be async at all? I am only looking to return stream. (Is that okay?)" is that it makes no difference to the caller, it only changes how your code looks (but not how it works).

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!