Click here to Skip to main content
15,886,026 members
Articles / Web Development / ASP.NET

Uploading and Viewing Images With ASP.NET MVC and Mongo DB

Rate me:
Please Sign up or sign in to vote.
4.73/5 (8 votes)
8 Jan 2014CPOL5 min read 64.5K   12   4
How to upload and view images with ASP.NET MVC and Mongo DB

The goal today is to create a small and quick ASP.NET MVC application that will allow us to upload and view images using MongoDB as the database. One of the methods for handling files with MongoDB is using Mongo’s GridFS specification. This method stores the file in chunks and stores those chunks in separate documents. The method we will use is more of a “classic” way to store images in databases. We will simply convert the bytes of the image to a string and store it and do the reverse for viewing the image.

The Tools We’ll Need

  • Visual Studio (I’m using VS 2013 express)
  • The ASP.NET MVC framework (I’m using version 5)
  • A MongoDB server instance (I’m running mine locally with the default settings)
  • Already be little familiar with MVC and the mongoDB in general

Let’s Get Started

First, we’ll need to create a new web application proeject. Go to File on the menu and select “new project”.

NewProject

On the next screen, select MVC with the default settings.

SelectMVC

We now have a basic MVC web application template. Next, add a new controller by right-clicking the Controllers folder and selecting “add” and then “Controller”. Select empty MVC 5 controller. We should now have an empty gallery controller like so:

galleryController

Get MongoDb Drivers From NuGet

To use the mongo database from this application, we will need to get the necessary drivers for C#. Open your Package Manager console and type the command:

Install-Package mongocsharpdriver

This will add the mongo c sharp drivers to your application from NuGet.

The Picture Model

Next, add a class to your models folder named MongoPictureModel.cs with the following:

C#
using MongoDB.Bson;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace MongoAndMVC.Models
{
public class MongoPictureModel
{
public ObjectId _id { get; set; }
public string FileName { get; set; }
public string PictureDataAsString { get; set; }
}
}

A couple of things to notice. We added a using statement for the “MongoDB.Bsonnamespace. We did this because we are using the type “ObjectId” which is a type native to mongo. Now that we have our model, we can now edit our controller with the need functions.

GalleryController.cs

Update the gallery controller like so…

C#
using MongoAndMVC.Models;
using MongoDB.Bson;
using MongoDB.Driver;
using MongoDB.Driver.Builders;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace MongoAndMVCTutorial.Controllers
{
public class GalleryController : Controller
{
public ActionResult Index()
{
var theModel = GetThePictures();
return View(theModel);
}

public ActionResult AddPicture()
{
return View();
}

[HttpPost]
public ActionResult AddPicture(HttpPostedFileBase theFile)
{
if (theFile.ContentLength > 0)
{
//get the file's name
string theFileName = Path.GetFileName(theFile.FileName);

//get the bytes from the content stream of the file
byte[] thePictureAsBytes = new byte[theFile.ContentLength];
using (BinaryReader theReader = new BinaryReader(theFile.InputStream))
{
thePictureAsBytes = theReader.ReadBytes(theFile.ContentLength);
}

//convert the bytes of image data to a string using the Base64 encoding
string thePictureDataAsString = Convert.ToBase64String(thePictureAsBytes);

//create a new mongo picture model object to insert into the db
MongoPictureModel thePicture = new MongoPictureModel()
{
FileName = theFileName,
PictureDataAsString = thePictureDataAsString
};

//insert the picture object
bool didItInsert = InsertPictureIntoDatabase(thePicture);

if (didItInsert)
ViewBag.Message = "The image was updated successfully";
else
ViewBag.Message = "A database error has occurred";
}
else
ViewBag.Message = "You must upload an image";

return View();
}

/// <summary>
/// This method will insert the picture into the db
/// </summary>
/// <param name="thePicture"></param>
/// <returns></returns>
private bool InsertPictureIntoDatabase(MongoPictureModel thePicture)
{
var thePictureColleciton = GetPictureCollection();
var theResult = thePictureColleciton.Insert(thePicture);
return theResult.Ok;
}

/// <summary>
/// This method will return just the id's and filenames of the pictures 
/// to use to retrieve the image from the db
/// </summary>
/// <returns></returns>
private List<MongoPictureModel> GetThePictures()
{
var thePictureColleciton = GetPictureCollection();
var thePictureCursor = thePictureColleciton.FindAll();

//use SetFields to just return the id and the name of the picture instead of the entire document
thePictureCursor.SetFields(Fields.Include("_id", "FileName"));

return thePictureCursor.ToList() ?? new List<MongoPictureModel>();
}

/// <summary>
/// This action will return an image result to render the data from the picture as a jpeg
/// </summary>
/// <param name="id">id of the picture as a string</param>
/// <returns></returns>
public FileContentResult ShowPicture(string id)
{
var thePictureColleciton = GetPictureCollection();

//get picture document from db
var thePicture = thePictureColleciton.FindOneById(new ObjectId(id));

//transform the picture's data from string to an array of bytes
var thePictureDataAsBytes = Convert.FromBase64String(thePicture.PictureDataAsString);

//return array of bytes as the image's data to action's response. 
//We set the image's content mime type to image/jpeg
return new FileContentResult(thePictureDataAsBytes, "image/jpeg");
}

/// <summary>
/// This will return the mongoDB picture collection object to use dor data related actions
/// </summary>
/// <returns></returns>
private MongoCollection<MongoPictureModel> GetPictureCollection()
{
//set this to what ever your connection is or from config
var theConnectionString = "mongodb://localhost";

//get the mongo db client object
var theDBClient = new MongoClient(theConnectionString);

//get reference to db server
var theServer = theDBClient.GetServer();

//gets the database , if it doesn't exist it will create a new one
string databaseName = "PictureApplication";//replace with whatever name you choose
var thePictureDB = theServer.GetDatabase(databaseName);

//finally attempts to get a collection, if not there it will make a new one
string theCollectionName = "pictures";
var thePictureColleciton = thePictureDB.GetCollection<MongoPictureModel>(theCollectionName);

return thePictureColleciton;
}
}
}

Let’s look at what we did here. The first thing that we did was add some new namespaces from the Mongo driver library to help us access the mongo DB and give us access to some very useful classes for manipulating the mongo data.

C#
MongoAndMVC.Models;
MongoDB.Bson;
MongoDB.Driver;
MongoDB.Driver.Builders;

We also added the System.IO namespace for some of the byte manipulation that we’ll be doing.

GetPictureCollection Function

This function goes through the process of giving us a MongoCollection<T> object that we can use for inserting and retrieving data. If the database or collection does not exist, the mongo database will create it on the fly.

ShowPicture Action

This action retrieves the picture data using the id passed in the URL. It will then take the data retrieved that was stored in string format and convert back to an array of bytes. Since we are returning a FileContentResult, this action will take the bytes and return them in the response in the designated “image/jpeg” mime type.

GetThePictures Function

This function returns a list of the MongoPictureModel objects retrieved from the database. The thing we did different here is use the SetFields function to reduce the fields we bring back. For the gallery page, we will only need the filename and ids of the pictures and not the data. We will get the image data from the individual calls to the ShowPicture action. For the Gallery view, we only need to render the filename and id (which we use to make the URL for image tag’s src attribute).

AddPicture Post Action

This action is the meat of what we are doing, but is very simple. First, we use the HttpPostedFileBase object that is passed in from the file type input control in the view. We check to make sure that we have a file there, then we get the file’s name. We will use this for the FileName property of the MongoPictureModel object we will create. Next, we get the content stream of the file passed in and convert it to an array of bytes. We then convert that array of bytes into a base64 encoded string. We use this data for the PictureDataAsString property of our MongoPictureModel. We then take our newly created model and pass it to our “InsertPictureIntoDatabase” function.

Make your way back to the index view for the gallery controller and edit it to match this…

ASP.NET
@model List<MongoAndMVC.Models.MongoPictureModel>
@{
ViewBag.Title = "Gallery";
}

<h2>Gallery</h2>

@Html.ActionLink("Add a new Picture", "AddPicture")

@foreach (var pictue in Model)
{
<div>
@pictue.FileName<br />
<img src="@string.Format("/Gallery/ShowPicture/{0}",pictue._id.ToString())" alt="@pictue.FileName" />
</div>
}

In the same directory, create a view named AddPicture.cshtml for the AddPicture actions with this…

ASP.NET
@{
ViewBag.Title = "Upload an image";
}

<h2>Upload a new image</h2>
@Html.ActionLink("View Gallery", "Index")

<div>
@if (ViewBag.Message != null && ViewBag.Message != "")
{
@ViewBag.Message
}
</div>

<form action="" method="post" enctype="multipart/form-data">
<input type="file" id="theFile" name="theFile" />
<br />
<button type="submit">Upload Image</button>
</form>

Also edit the layout.cshtml file in the shared folder under views and add a link to the index action of the gallery controller in the app’s navigation.

Let’s Test It Out

Alright, fire up your web app and traverse to the gallery controller by going to “localhost/Gallery”. You should get something like this:

GalleryPage

As you can see, we do not have any images yet, but we will soon rectify that. Click the “Add a new Picture” link and it should take you to the “Add a New Picture” page.

AddPicturePage

Simply click the input control and select a jpeg image to upload. If everything goes good, you should get the “The image was updated successfully” message from the AddPicture’s http post action.

WentGoodMessage

Click “View Gallery” and go back to the gallery page. You should see your newly uploaded image loaded straight from a mongo database.

GoodUploadGallery

Nice!

Additional Notes

  • You should carefully review the MongoDB documentation to come up with a file storage mechanism that’s more suited to your needs. The GridFS specification has its advantages (like no 16MB size limit) as well as some disadvantages vs storing files directly in the document vs just storing them on the file system.
  • This is just a tutorial, but if you are going to use some kind of method of image retrieval and display similar to this, you will be wise to come up with strategies to help alleviate the load on the DB such as paging and server side caching.

Download source files.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
United States United States
Software developer in Nashville, TN(USA).

Comments and Discussions

 
QuestionUnwanted space is appearing after image Pin
Am Gayathri18-May-15 2:55
Am Gayathri18-May-15 2:55 
QuestionAdjust the image size Pin
Member 1124206516-Dec-14 15:31
Member 1124206516-Dec-14 15:31 
Questionunable to connect to the server localhost Pin
Member 1084862529-May-14 20:03
Member 1084862529-May-14 20:03 
AnswerRe: unable to connect to the server localhost Pin
SleepyCrat2-Jun-14 8:26
SleepyCrat2-Jun-14 8:26 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.