ASP.Net MVC: Upload Image to Database and Show Image “Dynamically” Using a View

Oddly enough this came about from me wanting to do this, figuring it out, and then deciding not to bother with it. So there’s a possibility this will happen to you too. Well that’s not completely true. The first half where I was uploading and showing from a database, but showing an image through a view to mimic the .ashx functionality of WebForms is still pretty useful.

Saving the Image

First off, here’s the look of the table:

Table

So pretty simple table. Most important parts are the ImageData and ContentType. Why? Well let’s look at the action needed to save the image:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Upload(PhotoForSingleItem photo)
{
  //PhotoForSingleItem is just a class that has properties
  // Name and Alternate text.  I use strongly typed Views and Actions
  //  because I'm not a fan of using string to get the posted data from the
  //  FormCollection.  That just seems ugly and unreliable to me.

  //PhotoViewImage is just a Entityframework class that has
  // String Name, String AlternateText, Byte[] ActualImage,
  //  and String ContentType
  PhotoViewImage newImage = new PhotoViewImage();
  HttpPostedFileBase file = Request.Files["OriginalLocation"];
  newImage.Name = photo.Name;
  newImage.Alt = photo.AlternateText;

  //Here's where the ContentType column comes in handy.  By saving
  //  this to the database, it makes it infinitely easier to get it back
  //  later when trying to show the image.
  newImage.ContentType = file.ContentType;

  Int32 length = file.ContentLength;
  //This may seem odd, but the fun part is that if
  //  I didn't have a temp image to read into, I would
  //  get memory issues for some reason.  Something to do
  //  with reading straight into the object's ActualImage property.
  byte[] tempImage = new byte[length];
  file.InputStream.Read(tempImage, 0, length);
  newImage.ActualImage = tempImage ;

  newImage.Save();

  //This part is completely optional.  You could redirect on success
  // or handle errors ect.  Just wanted to keep this simple for the example.
  return View();
}

And here’s the mark up to get this ball a rollin’:

<form method="post" enctype="multipart/form-data" action="Photo/Upload">
  <div>
    <span>
     Name:
   </span>
   <span>
     <input type="text" id="Name" name="Name" />
   </span>
  </div>
  <div>
    <span>
      Alternate Text:
    </span>
    <span>
     <input type="text" id="AlternateText" name="AlternateText" />
    </span>
  </div>
  <div>
    <span>
      Image
    </span>
    <span>
      <input type="file" id="OriginalLocation" name="OriginalLocation" />
    </span>
  </div>
  <div>
    <input type="submit" value="Upload" />
  </div>
</form>

Biggest thing to notice in the markup is the enctype=”multipart/form-data”. This is a must to upload images. It was something I was missing originally and annoyed the hell out of me.

Showing the Image

So now that we have a we to upload the image, how the hell do you use it? Well that’s not too hard. It just involves a new type of result, an action, and an img element.

So the first thing you need is an image result, and in using my superior intellect I came up with such a thing. And by superior intellect I mean I used StackOverflow. Oddly enough though, it’s actually the second post that I got it from and I changed it a little. However, it was very useful.

using System.Web;
using System.Web.Mvc;
using System.IO;

public class ImageResult : ActionResult
{
  public String ContentType { get; set; }
  public byte[] ImageBytes { get; set; }
  public String SourceFilename { get; set; }

  //This is used for times where you have a physical location
  public ImageResult(String sourceFilename, String contentType)
  {
    SourceFilename = sourceFilename;
    ContentType = contentType;
  }

  //This is used for when you have the actual image in byte form
  //  which is more important for this post.
  public ImageResult(byte[] sourceStream, String contentType)
  {
    ImageBytes = sourceStream;
    ContentType = contentType;
  }

  public override void ExecuteResult(ControllerContext context)
  {
    var response = context.HttpContext.Response;
    response.Clear();
    response.Cache.SetCacheability(HttpCacheability.NoCache);
    response.ContentType = ContentType;

    //Check to see if this is done from bytes or physical location
    //  If you're really paranoid you could set a true/false flag in
    //  the constructor.
    if (ImageBytes != null)
    {
      var stream = new MemoryStream(ImageBytes);
      stream.WriteTo(response.OutputStream);
      stream.Dispose();
    }
    else
    {
      response.TransmitFile(SourceFilename);
    }
  }
}

And here’s how you use the actual result.

[AcceptVerbs(HttpVerbs.Get)]
public ActionResult ShowPhoto(Int32 id)
{
  //This is my method for getting the image information
  // including the image byte array from the image column in
  // a database.
  PhotoViewImage image = PhotoViewImage.GetById(id);
  //As you can see the use is stupid simple.  Just get the image bytes and the
  //  saved content type.  See this is where the contentType comes in real handy.
  ImageResult result = new ImageResult(image.ActualImage, image.ContentType);

  return result;
}

And the markup would go a little sumthin’ like dis:

  <img src="/Photo/ShowPhoto/1" alt="" />

And now you too can upload an image to a database, show it, and then decide just to physically host the images anyway. Next post will be about how to use this with jQuery and asynchronously. I bet you can’t wait!

51 thoughts on “ASP.Net MVC: Upload Image to Database and Show Image “Dynamically” Using a View”

  1. Ah well done, very cool.
    I am new to MVC and have written much the same to upload the images…I was about to revert to asp.net and create an httpHandler to stream the image out when I thought…someone somewhere must have done this in MVC before!
    Cheers,
    Steve

    1. Do you mean the ImageResult class? If so, that’s really just preference. Personally I wouldn’t have it straight on the controller since it could be used elsewhere in other projects.

      Even if you aren’t going to have other projects, I have a general
      rule of only one class per file for easier lookup and cleaner class files. There might be a chance you will have other result classes too so it wouldn’t hurt to have a ActionResult folder or something like that. The reason I don’t have a namespace to denote that it’s in a seperate area is just to keep the example simple.

      Mind you there are other school of thoughts, mainly people who don’t like folder clutter ie a million class files. They rely more on just namespaces to sort through the mess. Just depends on your style.

  2. Is caching the image as simple as changing the response's Cache properties in the ExecuteResult method? Surely it can't be that simple!

    1. I will look for it tonight as far as recovering the old project, since it might have been a casualty of the move. The semi finished one is a bit more complex than this post.

  3. Hi

    is it possible to send my a copy codes for working version. As I am new to MVC need a working example to follow. Thanks

  4. Why not just use FileResult?
    public ActionResult GetImage()
    {
    PhotoViewImage image = PhotoViewImage.GetById(id);

    return File(image.ActualImage, image.СontentType);
    }

    1. Wish I could tell you. It’s either that it didn’t work for what I wanted or this post is older than that result. Or I’m dumb. So there’s three possibilities for yo.

  5. Hi Sean,
    I like this article, Did you try to display many images in the View? Your sample is a single image display.

    thanks

    1. Far as I remember, and it’s been a while, I did in fact build a site that multiple images shown in one view. I really wish I could find the example project I had for this up and running.

  6. Hi. It is difficult to me to understand structure of the written a little. You couldn’t send a detail design, or at least a project part in which the given text is used. Thankful in advance.
    nunjax@gmail.com

  7. ..I’ve been able to implement all the code provided. It’s a little challenging because I’m trying to adhere to the Model View ViewModel methodology.
    At the moment my code is displaying a Red X. In DEBUG I’m hitting the ShowPhoto ActionResult. I can also trap in “public class ImageResult : ActionResult” at the “public ImageResult(byte[] sourceStream, String contentType)”.
    However, it doesn’t seem to enter “public override void ExecuteResult(ControllerContext context)”.

    1. I found my mistake…
      In my Image Controller I had modified Sean’s “public ActionResult ShowPhoto(Int32 id)” code incorrectly.
      Instead of “return Photo” I was using return “View(Photo)”. Once I corrected that everything is working.

  8. Thanks fot this example – although I can’t get it to work, it’s still the most meanigful example of posting an image to a database using MVC that I’ve found. As a complete newbie to MVC, would you mind sending the project please…I’m afraid I need more guidence through the example. Thanks in advance, Robert

        1. So various things have derailed me. I got it to compile just fine, but entity framework was out of sync with the database design. And as it’s Entity Framework 1 (Old project), I just haven’t had the time to deal with it’s “quirks”. If you still want the source though, I can post that. It does have the original database build scripts too.

          1. If you wouldn’t mind – I’d really appreciate it – I’m at a loss so far – so any pointers from your project would be gratefully received. Thanks, Rob

    1. I agree that this is the best example. Why? For me, simply because it had the html markup. Kind of important. I’m not using EntityFramework, but instead just good ol’ sprocs and a data layer that hits said sprocs. Maybe I’ll get up to speed someday with the LINQ the kids are all abuzz with.

  9. Great article. I was looking for MVC.Net implementation of this and this gave me a good idea.

    One issue though. I can’t get it to work with PDF files. It woks fine with plain text files, images, and MS Word files, but when it comes to PDFs, nothing comes up. It looks like the browser is trying to load something but it goes nowhere. Troubleshooting but could use some input. Thanks.

  10. Just to clarify my question above, when I say “nothing comes up”, I mean when I try to display the document by returning the either the ImageResult or even File(..).

  11. Object reference not set to an instance of an object.
    when uploading image this error is shown………. code are here………

    photo.contenttype

  12. Sean, please, could you send me a project or main source files? This is the only adequate article, but I can’t make this stuff working 🙁

  13. What I’d hoped to do was to upload an image via ajax, as I’m quite fond of that, maybe too much. Anyway, I’ve found exactly one item on the internet. It was a fellow on the jQuery website asking the same question. So I relented and just used an old-school form.

    If anyone wants to take up the task of doing something like this ajax-style, and does so successfully, you’ll be my hero and I will borrow your code.

    1. Wait a sec, you said in your next post you’d do just this. Well, I guess you’re my hero now. And I need to read to the end from now on.

  14. where is   source project  file?
    thank you very much.
    i don’t know that if use Code-First ,how mapping image type in database.
    i see ,someone code like this :
    public HttpPostedFileBased Picture;
    i try,but not work.
    so …i wana source project, oh….please help!!

  15. You omitted the newImage.Save() function. Do we write this ourselves. I don’t have a clue where to start. Advise please. Otherwise Excellent

  16. Hi i cant show image in mvc view i few changes in code.Need to use

    ContentType in ImageResult?

  17. How can i show image in view if i haven’t a image content type i just store a byte[] Image in db with “Image” data type

  18. hi, i need some idea for edit an image .. i have some badges in image type.. i want user can change the content of image… like a name over pen or mug and the new image will save in database… please help,,, i am new in mvc… thanks in advance

Comments are closed.