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:
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!
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
Don’t be a cheater. No one likes a cheater… Unless you play Baseball.
Newbie question; where should I create the custom actionresult class? Any specific folder or just inside the controller?
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.
Is caching the image as simple as changing the response's Cache properties in the ExecuteResult method? Surely it can't be that simple!
I'm not sure it is preventing any specific image from being cached, but more so that no images are being cached.
Could you send the PhotoViewImage class to me ?
THX very much
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.
Thanks.
Very nice! Thanks a bunch.
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
could you upload the source project files?
yes we can
Why not just use FileResult?
public ActionResult GetImage()
{
PhotoViewImage image = PhotoViewImage.GetById(id);
return File(image.ActualImage, image.áontentType);
}
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.
Hi Sean,
I like this article, Did you try to display many images in the View? Your sample is a single image display.
thanks
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.
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
I can’t promise I can still find the example, but I’ll do some searching.
..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)”.
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.
Yay
Sean,
Just want to say thanks. This was a great example that helped me a lot!
Glad to know you found something useful on this site. I, however, have yet to do so.
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
I actually found it and currently trying to update it so it works again. Might have it done tomorrow.
That’s really kind of you – thanks so much. Rob
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.
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://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.
Yes I agree
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.
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.
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(..).
Please send the class file PhotoViewImage to iamseban@gmail.com
Object reference not set to an instance of an object.
when uploading image this error is shown………. code are here………
photo.contenttype
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 🙁
Works perfectly for me, this help me a lot thx for share. =)
Great example. Thanks very much!
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.
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.
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!!
This is all bullshit code – don’t waste you time here
To be fair it is 3 years old, but on the other hand your comment sums up most of my site.
Hi. Could you send me a project of this example?. I have few problems to resolve. on marcjacs@gmail.com
You omitted the newImage.Save() function. Do we write this ourselves. I don’t have a clue where to start. Advise please. Otherwise Excellent
Hi i cant show image in mvc view i few changes in code.Need to use
ContentType in ImageResult?
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
Could you please implement the PhotoViewImage class here?
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