File Upload with ASP.Net Web API

I recently had the opportunity to create a new RESTful service for the project I was developing for my employer. As this service would be used internally, it was the perfect opportunity to try a technology that was new to me: ASP.NET Web API.

This new service would enable the caller to upload and download images. This is nothing particularly unique as there are many excellent examples on the web that demonstrate some flavor of this. All these solutions call System.Net.Http.MultipartFormDataStreamProvider to write the image file to disk. In my case, I wanted to store the image binary in a SQL Server table so I used the System.Net.Http.MultipartMemoryStreamProvider class to allow me to read the contents of the request and send the image stream to the method that wrote to the database.

As I was developing with Visual Studio 2010, I could not use the new await functionality.

public Task<IEnumerable<int>> Post()
{
  if (!Request.Content.IsMimeMultipartContent())
  {
    throw new HttpResponseException(Request.CreateResponse(
	HttpStatusCode.NotAcceptable, 
	"This request is not properly formatted"));
  }

  try
  {
    var streamProvider = new MultipartMemoryStreamProvider();
    var task = Request.Content.ReadAsMultipartAsync(streamProvider)
	      .ContinueWith<IEnumerable<int>>(t =>
    {
      if (t.IsFaulted || t.IsCanceled)
      {
        throw new HttpResponseException(HttpStatusCode.InternalServerError);
      }

      var addedId = streamProvider.Contents.Select(i =>
      {
        Stream stream = i.ReadAsStreamAsync().Result;                      

        // Insert your own code to deal with the Stream.  
        // In my case, I called my code that wrote the image to 
        // database and returned the image's id in imageId such as below.
        int imageId = DatabaseCode(stream);
        return imageId;
      });
      return addedId;
    });
    return task;
  }
  catch (Exception ex)
  {
    throw new HttpResponseException(Request.CreateResponse(
	HttpStatusCode.NotAcceptable, 
	"Error: " + ex.Message));
  }
}

This is a minor tweak to the code from the samples linked above but I thought this might be of use to the next person, or even my future self, who attempts to store images elsewhere than directly to disk as I had to do.

If you found this post helpful or wish to constructively point out improvements, leave me a comment!

Happy coding!