Click here to Skip to main content
Click here to Skip to main content

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

, 8 Jan 2014
Rate this:
Please Sign up or sign in to vote.
Download Source Files 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 chunk

Download Source Files

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 a 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 you models folder named MongoPictureModel.cs with the following


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.Bson” namespace. 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…


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 occured";
}
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 pictrue 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. 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.

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 propert 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…


@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…


@{
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 it’s 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)

About the Author

SleepyCrat
Software Developer
United States United States
Software developer in Nashville, TN(USA).
Follow on   Twitter

Comments and Discussions

 
Questionunable to connect to the server localhost PinmemberMember 1084862529-May-14 20:03 
AnswerRe: unable to connect to the server localhost PinmemberSleepyCrat2-Jun-14 8:26 

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

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

| Advertise | Privacy | Mobile
Web02 | 2.8.140721.1 | Last Updated 8 Jan 2014
Article Copyright 2014 by SleepyCrat
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid