Returning Images from ASP.NET Web API


Desktop-as-a-Service Designed for Any Cloud ? Nutanix Frame


Sometimes you need to save and retrieve image data in SQL Server as a part of Web API functionality. A common approach is to save images as physical image files on the web server and then store the image URL in a SQL Server database. However, at times you need to store image data directly into a SQL Server database rather than the image URL. While dealing with the later scenario you need to read images from a database and then return this image data from your Web API. This article shows the steps involved in this process.

SQL Server Database and EF Data Model

An image is a binary piece of data. When it comes to storing images directly into a SQL Server database, developer's use Image or Varbinary data types for such columns. To save and retrieve image data from your .NET applications (including Web API) you need to use byte arrays. Let's try to understand this with a simple example. Begin by creating a new ASP.NET MVC project and select template as Web API. Then add a new SQL Server database in the App_Data folder. Name the database as ImageDb.

Add New Item
Add New Item

Then add a table in the newly added SQL Server database matching the following schema.

Add a New Table
Add a New Table

The Images table shown above has two columns - Id and ImageData. Notice that data type of the ImageData column is varbinary(MAX). The varbinary data type can take any binary data including images and files.

Now add an Entity Framework data model for the ImageDb database in the Models folder.

Entity Framework Data Model
Entity Framework Data Model

You will notice in the properties window of the ImageData column that its data type is set to Binary. 

Uploading Image Files

Although our main interest is to see how images are returned from an ASP.NET Web API, you need to add a few sample images inside the Images table that you can retrieve later. This requires that you upload files from the client machine and store them in the Images table. To do so, add Index view for the Index() action method of the HomeController (this controller class is added by default when you create a new Web API project). The HTML markup of the view is shown below:

    <form id="form1">
        <input type="file" id="file1" multiple="multiple" />
        <input type="button" id="btnUpload" value="Upload" />
        <input type="button" id="btnShow" value="Show" />
        <br />
        <br />
        <div id="imgContainer"></div>

As you can see the Index view contains a file input field. Notice that the multiple attribute of the file input field is set so that you can upload multiple files at a time. The btnUpload triggers the file upload process. The other HTML elements (btnShow and imgContainer) are used during image retrieval process.

Now, add the following jQuery code in the click event handler of the btnUpload button.

$("#btnUpload").click(function () {
  var files = $("#file1").get(0).files;
  if (files.length > 0) {
    var data = new FormData();
    for (i = 0; i < files.length; i++) {
      data.append("file" + i, files[i]);
      type: "POST",
      url: "/api/images",
      contentType: false,
      processData: false,
      data: data,
      success: function (results) {
        for (i = 0; i < results.length; i++) {

We won't go into much details of this code here. If you are not familiar with file upload using Web API read this article to learn more. This code basically makes a POST request to the Images Web API and passes selected files as FormData object. You will develop the Images Web API shortly.

Now, open the default ApiController class from the Controllers folder and rename it to ImagesController. Then add the following Post() method to the ImagesController class.

public Task<IEnumerable<string>> Post()
  if (Request.Content.IsMimeMultipartContent())
    string fullPath = HttpContext.Current.Server.MapPath("~/uploads");
    MultipartFormDataStreamProvider streamProvider = new MultipartFormDataStreamProvider(fullPath);
    var task = Request.Content.ReadAsMultipartAsync(streamProvider).ContinueWith(t =>
      if (t.IsFaulted || t.IsCanceled)
        throw new HttpResponseException(HttpStatusCode.InternalServerError);
      var fileInfo = streamProvider.FileData.Select(i =>
        var info = new FileInfo(i.LocalFileName);
        ImageDbEntities db = new ImageDbEntities();
        Image img = new Image();
        img.ImageData = File.ReadAllBytes(info.FullName);
        return "File uploaded successfully!";
     return fileInfo;
    return task;
    throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotAcceptable, "Invalid Request!"));

The Post() Web API method basically grabs the files uploaded by the end user and saves them into the Images table. The Post() method uses asynchronous processing as indicated by the Task object. Notice the code marked in bold letters. It creates an instance of Image model class and sets its ImageData property. As mentioned earlier ImageData is a byte array. To read data from the uploaded file into a byte array you use the File.ReadAllBytes() method. The newly created Image object is then added to Images and SaveChanges() is called. The Post() method returns an IEnumerable of strings, each string is a success message in this case.

Now, run the project, select a few image files and upload them in the Images table. 

Retrieving Image Files

Now, add a method - Get() - to the Web API as shown below:

 public List<int> Get()
  ImageDbEntities db = new ImageDbEntities();
  var data = from i in db.Images
             select i.Id;
  return data.ToList();

The Get() method takes no parameters and returns a generic List of integers. These integers are nothing but image IDs.

Next, add another Get() method, this time accepting an id parameter.

public HttpResponseMessage Get(int id)
  ImageDbEntities db = new ImageDbEntities();
  var data = from i in db.Images
             where i.Id == id
             select i;
  Image img = (Image)data.SingleOrDefault();
  byte[] imgData = img.ImageData;
  MemoryStream ms = new MemoryStream(imgData);
  HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
  response.Content = new StreamContent(ms);
  response.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("image/png");
  return response;

Notice that the return type of the above Get() method is HttpResponseMessage. The HttpResponseMessage class from System.Net.Http represents an HTTP response that includes the HTTP status code and the response data. The Get() method accepts an Image id that is to be retrieved. Inside, it fetches the Image from the database and puts the ImageData in a byte array. A new MemoryStream is then created based on this byte array. A new instance of HttpResponseMessage is created with an HTTP status code of OK. The Content property of the HttpResponseMessage represents the content of the HTTP response. In this case the Content property is set to a new StreamContent object. The MemoryStream is passed in the constructor of the StreamContent object. The ContentType header of the response message is set to image/png using the MediaTypeHeaderValue. Finally, the HttpResponseMessage instance is returned from the Get() method.

Now, add the following jQuery code in the Index view.

$("#btnShow").click(function () {
  var options = {};
  options.url = "api/images";
  options.type = "GET";
  options.dataType = "json";
  options.contentType = "application/json";
  options.success = function (results) {
    for (var i = 0; i < results.length; i++) {
      $("#imgContainer").append("<img src='" + "api/images/" + results[i] + "' /> <br />");
  options.error = function (err) { alert(err.statusText); };

The click event handler of the Show button makes an Ajax request to the Get() method. Recollect that this Get() method returns a generic List of integers. In the success function a for loop iterates through all the Image ids and appends an <img> element to the imgContainer. Notice how the src attribute of the <img> tag is specified. It is of the form api/images/<image_id>. This way when the src attribute is set it actually invokes the Get() method of the Web API along with the Image id value. The Get() method returns an HttpResponseMessage whose content is nothing but the actual image data. Thus specifying the src attribute in this fashion displays the corresponding image. The following figure shows a sample run of the application.

 Sample Run
Sample Run


In order to return images stored directly in a SQL Server database from an ASP.NET Web API you need to create a Get() method that returns HttpResponseMessage. The Content property of the HttpResponseMessage class represents the binary image data associated with an image. In your HTML markup you can use image URLs that trigger the Get() method by passing an image ID. Using the approach illustrated in this article you can develop a Web API to store and retrieve images to and from a SQL server database.



  • Thanks

    Posted by Piter Machado on 04/12/2018 10:46pm

    Thanks! This was really helpful to me! Very simplified way and it works.

  • ImageUpload

    Posted by shilpa on 01/04/2018 10:00am

    Image Upload choosen path completely..example one image download save it...select the file drag to the chrome browser path will be displayed...thats how to get the image in web api controller

  • Great tutorial

    Posted by Alan on 05/20/2015 02:57am

    I need to do this, I saw the code and it seems exactly what I need, I'll test it as soon as I get home. P.D. Theme makes this site really hard to read.

  • Content is good but the theme used in terrible

    Posted by josh william on 03/04/2015 06:57am

    The theme used makes it very difficult to read

  • Thanks

    Posted by Ibrahim Islam on 02/20/2015 10:18pm

    Thank you very much this really helped.

  • IT

    Posted by Pablo on 01/27/2015 12:40pm

    Any idea why I might be receiving the following upon clicking "Upload"? POST http://localhost:49603/Images 405 (Method Not Allowed) jquery-2.1.3.js:8625 sendjquery-2.1.3.js:8161 jQuery.extend.ajax(index):25 (anonymous function) jquery-2.1.3.js:4430 jQuery.event.dispatchjquery-2.1.3.js:4116 elemData.handle

  • awesome

    Posted by billa on 01/14/2015 02:11pm

    awesome really helpful , thank you very much please keep posting new post

  • Web Service

    Posted by Jimmy Davila on 01/12/2015 08:03pm

    Very Good Post Can you do the same using web services? with the same database. I'm working on a project that I have to upload and download files from SQ: 2008. Displaying them in a gridview and I need to be able to download the file on row click event from the gridview. Your help will be greatly appreciated. Best Regards.

  • You must have javascript enabled in order to post comments.

Leave a Comment
  • Your email address will not be published. All fields are required.

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date