Using pictures in ASP.NET MVC Core with Entity Framework Core
Using pictures in ASP.NET Core MVC is not always very straightforward. A lot of articles you find simply upload the pictures to a www-folder and use them from there. This may work if you host your own website. This approach will give problems when using a cloud service. A cloud service may terminate your deployed version and may spin up a new fresh version to replace the old one. All pictures uploaded to the www-folder will then be lost and your database will have references to resources on the file system that do not exist anymore. In this post, I will show you how to store the images in your database and use them from there.
The code for this blog post can be found here.
For this example, I create a simple application to upload a profile to a website. I deliberately don't pay attention to the layout of the site, because it will only distract you from the meaningful code.
I have created a regular ASP.NET Core MVC 6 application using the templates available in Visual Studio 2022. This same code can be created in older versions of MVC Core as well. The generation step results in the following code being generated. In the code, the Migrations folder for Entity Framework is included as well.
The first thing to do in an MVC application is of course create a controller and action method to allow the user to upload an image. In the example code, I created the UserController for this. The action method to show a form to the user hardly contains any code.
On the corresponding HTML page, a form is needed to specify the name of the person and an upload input element. The enctype for the form must be set to "multipart/form-data". In the input element, I can specify what kind of picture I want to support.
This view is strongly typed to a view model.
Within this class, the name property is a normal string. For the uploaded file, we need to use the type IFormFile.
The running application will show the following form.
Once the user enters a name, chooses an image and presses the "CreateProfile" button, a separate action method in the UserController is called.
The action method does of course start with some housekeeping to check the contents of the received parameters. Given the received viewmodel a new User-class can be instantiated. This class has the following code.
The user name is passed in the viewmodel and can be safely copied to the new User object. The picture format is not passed directly to the action method but can be retrieved from the IFormFile parameter.
The contents of the file are stored as a stream in the IFormFile object. For storage in the database, this stream has to be converted into a byte array. Fortunately, this can be easily done by using a MemoryStream.
The user object is now completed filled, so it can be stored in the database in the normal Entity Framework way.
The saved profile can be retrieved in a different action method.
The user is retrieved from the injected context using a normal LINQ query. For the display, a different viewmodel is used. Showing a picture from the database needs a base64-encoded string, so the string type is used for the picture. The format of the picture is also passed to the viewmodel.
In the corresponding view, this model can be retrieved to show the image.
The src of the image must be set to "data:picture format;base64" together with the base64 encoded string.
When we now run the application, the uploaded image is shown.