tcarvin
tcarvin

Reputation: 10855

Return immediate response from async ApiController

I've got a problem with returning an "immediate" response from an normally async ApiController. The code is below, looks for the exclamation points. The use-case is a content-type check fails and I want to send an error response message back. The first version hangs Visual Studion 2010 (and Fiddler). The second works.

My question is, why can't I use my initial approach of returning the dummy Task that merely passes back the response object?

public class MyController : ApiController
{

   public Task<HttpResponseMessage> Post([FromUri]string arg)
   {
       HttpResponseMessage response = null;

       // synchronous validation
       if (Request.Content.Headers.ContentType.MediaType != @"image/jpeg")
       {                    
           response = Request.CreateErrorResponse(
               HttpStatusCode.UnsupportedMediaType,
               "Invalid Content-Type.");
       }


       if (response == null)  // no immediate response, switch to async
       {
          // work done here    
       }
       else // immediate response, but we need to wrap in a task for caller to fetch
       {

           // !!!! this one doesn't work !!!
           return new Task<HttpResponseMessage>( () => response);

           // !!! this one does !!!
           TaskCompletionSource<HttpResponseMessage> tcs = new TaskCompletionSource<HttpResponseMessage>();
           tcs.SetResult(response); 
           return tcs.Task;

       }
    }
}

Upvotes: 1

Views: 2909

Answers (1)

svick
svick

Reputation: 244928

The constructor of Task<T> returns a task that is not started yet, for it to work, you would have to do something like:

var task = new Task<HttpResponseMessage>(() => response);
task.Start();
return task;

But doing so is inefficient, because of the lambda that unnecessarily executes on the thread pool. Your second version is better and in .Net 4.5 an even better version would be to use Task.FromResult():

return Task.FromResult(response);

Upvotes: 8

Related Questions