How to Upload Files and Save in Database in ASP.NET Core MVC

In this Part, we are going to learn how to upload files and store in a Database in ASP.NET Core MVC in a step by step way.

  • Creating ASP.NET Core Application
  • Database Design
  • Adding Controller
  • Adding View
  • Adding Index Action Method to Handle POST Request
  • Uploading Image
  • Output

We are going to create ASP.NET Core Web Application for that we are going to choose ASP.NET Core Web Application template.

Creating ASP.NET Core Application

Next, we are going to set Project Name WebApplication12 and location and in last part, we are going to choose .Net Core framework and ASP.NET Core Version 3.0 as the framework for application and few advance settings for such as configuring https and enabling docker we are not going to enable docker settings for this project.

Now finally click on create button to create a project.
Project structure
The project structure generated according to the configuration.

Database Design

First, we need to create a table for storing the uploaded files for that we are going to create a table with the name Files.

Script to Create Files Table

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[Files](
	[DocumentId] [int] IDENTITY(1,1) NOT NULL,
	[Name] [varchar](100) NULL,
	[FileType] [varchar](100) NULL,
	[DataFiles] [varbinary](max) NULL,
	[CreatedOn] [datetime] NULL,
 CONSTRAINT [PK_Files] PRIMARY KEY CLUSTERED 
(
	[DocumentId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, 
IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, 
ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO

After creating a table next, we are going to Add Entity framework reference to project from the NuGet package.

Adding Entity Framework Core package from NuGet

For adding a package from NuGet right-click on Main project WebApplication12 and from the menu select Manage NuGet Packages. As you select it a New dialogue of NuGet Package Manager with search box will pop up.

In choose browse tab and search Microsoft.EntityFrameworkCore.SqlServer and choose version 3.0.0 the latest version of Microsoft.EntityFrameworkCore.SqlServer is in the preview that why we have chosen them, finally click on the install button for adding the package.

After adding Microsoft.EntityFrameworkCore.SqlServer to project next, we are going to Configuring Connection string in appsettings.json.

Configuring Connection string in appsettings.json

Here in ASP.NET core, we don’t have web.config file which was there in the older version of ASP.NET and ASP.NET MVC here we have appsettings.json file where we are going to keep application-level settings, and this file is Json based.

appsettings.json file

In this file, we have added ConnectionStrings section inside that we have added DatabaseConnection key and other is value.

Notice: – here I am using SQL based authentication for database connection that why I have added User Id and password of SQL server.

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*",
  "ConnectionStrings": {
    "DatabaseConnection": "Data Source=SAI-PC\\SQLEXPRESS; initial catalog=AllSampleCode; user id=sa; password=Pass$123"
  }
}

Next, after adding the connection string, we are going to add Files model in the Models folder.

Adding Files Model

using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace WebApplication12.Models
{
    [Table("Files")]
    public class Files
    {
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int DocumentId { get; set; }
        [MaxLength(100)]
        public string Name { get; set; }
        [MaxLength(100)]
        public string FileType { get; set; }
        [MaxLength]
        public byte[] DataFiles { get; set; }
        public DateTime? CreatedOn { get; set; }
    }
}

Next, after adding Files Model, we are going to add DatabaseContext Class and inheriting with DbContext class.

Adding DatabaseContext Class and inheriting with DbContext class

We are going to add DatabaseContext class which will inherit DbContext class, and DatabaseContext constructor accepts the DbContextOptions as an argument. The DbContextOptions carries the configuration information needed to configure the DbContext.

After adding DatabaseContext class, we have defined DbSet entity for Files Model.

Code Snippet

using Microsoft.EntityFrameworkCore;

namespace WebApplication12.Models
{
    public class DatabaseContext : DbContext
    {
        public DatabaseContext(DbContextOptions<DatabaseContext> options) : base(options)
        {
        }
        public DbSet<Files> Files { get; set; }
    }
}

After Configuring DatabaseContext class next, we are going Register DatabaseContext as a service.

Registering Dependency injection AddDbContext

In this part, we are going to register DatabaseContext class as a service for using it as dependency injection, which will be available to the entire application.
We are going to register this service in ConfigureServices Method of startup class.
First, we need to read connection string from appsettings.json file to pass it to register service.

Getting Connection String from appsettings.json

var connection = Configuration.GetConnectionString("DatabaseConnection");

Next, we are going to use AddDbContext extension method to register the DatabaseContext in the dependency injection container.

services.AddDbContext<DatabaseContext>(options => options.UseSqlServer(connection));

Use a ROW_NUMBER() in queries instead of OFFSET/FETCH. This method is backwards-compatible to SQL Server 2005 then register below method.

services.AddDbContext<DatabaseContext>(options => options.UseSqlServer(connection, b => b.UseRowNumberForPaging()));

ConfigureServices Method in Startup Class

public void ConfigureServices(IServiceCollection services)
 {
     //Getting Connection String from appsettings.json
     var connection = Configuration.GetConnectionString("DatabaseConnection");

     services.AddDbContext<DatabaseContext>(options => options.UseSqlServer(connection));
     // OR
     //services.AddDbContext<DatabaseContext>(options => options.UseSqlServer(connection, b => b.UseRowNumberForPaging()));

     services.AddControllersWithViews();
 }

Now we can use DatabaseContext class as service for dependency injection in the entire application. The next step we are going to add a controller.

Adding Controller

We are going to add a controller with Name Demo Controller after adding controller we have default Index action method in it.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;

namespace WebApplication12.Controllers
{
    public class DemoController : Controller
    {
        public IActionResult Index()
        {
            return View();
        }
    }
}

After adding Demo Controller and Index Action Method next we are going Add Index View.

Adding View

For Adding View just by right-clicking inside Index Action Method and from the list choose Add View option a new dialogue pops up which has View Name same as Action Method Name Index next we are not going to select Template and Model class for this View click on Add button to create View.

After Creating Index View Next, we are going to add Form tag with the encoding type “multipart/form-data” and set Controller and Action which handle Post Request an inside form tag we are going to add file input control and submit button (Upload).

Code Snippet

@{
    ViewData["Title"] = "Index";
}

<h1>Index</h1>
<div class="row">
    <div class="col-md-5">
        <form method="post" enctype="multipart/form-data" asp-controller="Demo" asp-action="Index">
            <div class="form-group">
                <div class="col-md-10">
                    <p>Upload file</p>
                    <input class="form-control" name="files" type="file" />
                </div>
            </div>
            <div class="form-group">
                <div class="col-md-10">
                    <input class="btn btn-success" type="submit" value="Upload" />
                </div>
            </div>
        </form>
    </div>
</div> 

Now Let’s Save and Run application and See How Index View is rendered with Controls.

After create Index View, Next we are going to add another Index action Method for handling POST request.

Adding Index Action Method to Handle POST Request

We are going to Add Another Action Method with name Index which handle POST request and take IFormFile as an input parameter.  And also, for accessing DatabaseContext in DemoController, we are going to use Constructor injection.

Note: – IFormFile interface contains all properties of the file which is posted such as Length, ContentType, Filename.

The Index Action Method takes IformFile as input in which IformFile interface contains Properties of the Posted file.
Next step we are going to valid Length of the posted file if it is greater then zero then we are going generate new file name, and then next we are going to create object of Files class and assign IformFile values to files object which we have created and then we are going to pass Files Model to Add method of DbContext which set entity set to Added When we call context.SaveChanges then an Insert statement is generated and executed by the database.

Code Snippet

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System;
using System.IO;
using WebApplication12.Models;

namespace WebApplication12.Controllers
{
    public class DemoController : Controller
    {
        private readonly DatabaseContext _context;
        public DemoController(DatabaseContext context)
        {
            _context = context;
        }
        public IActionResult Index()
        {
            return View();
        }

        [HttpPost]
        public IActionResult Index(IFormFile files)
        {
            if (files != null)
            {
                if (files.Length > 0)
                {
                    //Getting FileName
                    var fileName = Path.GetFileName(files.FileName);
                    //Getting file Extension
                    var fileExtension = Path.GetExtension(fileName);
                    // concatenating  FileName + FileExtension
                    var newFileName = String.Concat(Convert.ToString(Guid.NewGuid()), fileExtension);

                    var objfiles = new Files()
                    {
                        DocumentId = 0,
                        Name= newFileName,
                        FileType = fileExtension,
                        CreatedOn = DateTime.Now
                    };
                    
                    using (var target = new MemoryStream())
                    {
                        files.CopyTo(target);
                        objfiles.DataFiles = target.ToArray();
                    }

                    _context.Files.Add(objfiles);
                    _context.SaveChanges();

                }
            }
            return View();
        }
    }
}

After completed with adding Index Action Method along with constructor injection for injecting DatabaseContext dependency which uses for inserting uploaded file to the database. Next, we are going to Run Application and Test it by uploading an image.

Uploading Image

Debug View While Uploading file

Output

An image which we have uploaded got stored in Files tables.

By Saineshwar Bageri

I am Microsoft MVP | C# Corner MVP | Code Project MVP | FULL STACK .NET Developer and working on .Net Web Technology (Asp.net, Asp.net Core,.Net Core, C#, Sqlserver, MVC, Windows, Console Application, javascript, jquery, json, ORM Dapper) and also a freelance developer.