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!

Tags: ,

  • http://www.cadabrapacific.com Steve

    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

    • http://www.byatool.com Sean

      Don’t be a cheater. No one likes a cheater… Unless you play Baseball.

  • http://www.isyndica.com Carlos

    Newbie question; where should I create the custom actionresult class? Any specific folder or just inside the controller?

    • http://www.byatool.com Sean

      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.

  • http://www.vanick.com nathan

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

    • http://www.byatool.com Sean

      I'm not sure it is preventing any specific image from being cached, but more so that no images are being cached.

  • Endy

    Could you send the PhotoViewImage class to me ?

  • Endy

    THX very much

    • http://www.byatool.com Sean

      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.

      • Endy

        Thanks.

  • Vincent

    Very nice! Thanks a bunch.

  • Bez

    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

  • http://aspnet.aun.su Asp.Net

    could you upload the source project files?

    • Jay

      yes we can

  • bms

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

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

    • http://www.byatool.com Sean

      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.

  • http://n/a nic

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

    thanks

    • http://www.byatool.com Sean

      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.

  • Evgeniy

    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

    • http://www.byatool.com ByATool

      I can’t promise I can still find the example, but I’ll do some searching.

  • Cory

    ..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)”.

    • Cory

      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.

      • http://www.byatool.com ByATool

        Yay

  • Cory

    Sean,

    Just want to say thanks. This was a great example that helped me a lot!

    • http://www.byatool.com ByATool

      Glad to know you found something useful on this site. I, however, have yet to do so.

  • Robert

    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

    • http://www.byatool.com ByATool

      I actually found it and currently trying to update it so it works again. Might have it done tomorrow.

      • Robert Jukes

        That’s really kind of you – thanks so much. Rob

        • http://www.byatool.com ByATool

          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.

          • Robert Jukes

            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

          • http://www.byatool.com ByATool

            http://demo.byatool.com/PhotoViewTop.zip

            There it is. It’s a 2010 solution but doesn’t really need to be. If you don’t have 2010 you can always just create a new solution and include the projects.

          • John Doe

            Yes I agree

    • thohan

      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.

  • Markofny

    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.

  • Markofny

    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(..).

  • Iamseban

    Please send the class file PhotoViewImage to iamseban@gmail.com

  • Khaled_cse_07

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

    photo.contenttype

  • Bassist

    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 :(

  • http://twitter.com/imPillo Porfirio Valencia

    Works perfectly for me, this help me a lot thx for share. =)

  • Tim Stott

    Great example. Thanks very much!

  • thohan

    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.

    • thohan

      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.

  • Uiuiioio633

    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!!

  • John_wilson

    This is all bullshit code  – don’t waste you time here

    • http://www.byatool.com ByATool

      To be fair it is 3 years old, but on the other hand your comment sums up most of my site.

  • marcjac

    Hi. Could you send me a project of this example?. I have few problems to resolve. on marcjacs@gmail.com

  • Martin1971

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

  • tested

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

    ContentType in ImageResult?

  • tested

    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

  • daddy

    Could you please implement the PhotoViewImage class here?