Support us .Net Basics C# SQL ASP.NET Aarvi MVC Slides C# Programs Subscribe Download

File upload in asp.net core mvc

Suggested Videos
Part 50 - Entity framework core migrations | Text | Slides
Part 51 - Entity framework core seed data | Text | Slides
Part 52 - Keeping domain models and database schema in sync in asp.net core | Text | Slides

In this video we will discuss how to upload a file using ASP.NET Core MVC with an example.

We want to implement the following Create Employee Form. We want to be able upload Employee photo using the Photo field on the form.


asp.net core file upload example


When this Create Employee Form is submitted, we want to store Employee data i.e Name, Email, Department and PhotoPath in Employees database table. Here is the Employees database table. This table is created using Migrations in ASP.NET Core.

upload image in asp.net core

Employee photo should be uploaded to wwwroot/images folder on the web server.

Employee Model Class

public class Employee
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Email { get; set; }
    public Dept? Department { get; set; }
    public string PhotoPath { get; set; }
}

EmployeeCreateViewModel Class

public class CreateViewModel
{
    public string Name { get; set; }
    public string Email { get; set; }
    public Dept? Department { get; set; }
    public IFormFile Photo { get; set; }
}
  • IFormFile is in Microsoft.AspNetCore.Http namespace.
  • The file uploaded to the server can be accessed through Model Binding using the IFormFile interface.
  • The interface IFormFile has the following properties and methods
public interface IFormFile
{
    string ContentType { get; }
    string ContentDisposition { get; }
    IHeaderDictionary Headers { get; }
    long Length { get; }
    string Name { get; }
    string FileName { get; }
    Stream OpenReadStream();
    void CopyTo(Stream target);
    Task CopyToAsync(Stream target, CancellationToken cancellationToken = null);
}

Create View Code

The code specific to uploading the file is commented

@model EmployeeCreateViewModel

@{
    ViewBag.Title = "Create Employee";
}

@*To support file upload set the form element enctype="multipart/form-data" *@

<form enctype="multipart/form-data" asp-controller="home" asp-action="create"
      method="post" class="mt-3">
    <div class="form-group row">
        <label asp-for="Name" class="col-sm-2 col-form-label"></label>
        <div class="col-sm-10">
            <input asp-for="Name" class="form-control" placeholder="Name">
            <span asp-validation-for="Name" class="text-danger"></span>
        </div>
    </div>
    <div class="form-group row">
        <label asp-for="Email" class="col-sm-2 col-form-label"></label>
        <div class="col-sm-10">
            <input asp-for="Email" class="form-control" placeholder="Email">
            <span asp-validation-for="Email" class="text-danger"></span>
        </div>
    </div>

    <div class="form-group row">
        <label asp-for="Department" class="col-sm-2 col-form-label"></label>
        <div class="col-sm-10">
            <select asp-for="Department" class="custom-select mr-sm-2"
                    asp-items="Html.GetEnumSelectList<Dept>()">
                <option value="">Please Select</option>
            </select>
            <span asp-validation-for="Department" class="text-danger"></span>
        </div>
    </div>

    @*  asp-for tag helper is set to "Photo" property. "Photo" property type is IFormFile
        so at runtime asp.net core generates file upload control (input type=file)
    *@

    <div class="form-group row">
        <label asp-for="Photo" class="col-sm-2 col-form-label"></label>
        <div class="col-sm-10">
            <div class="custom-file">
                <input asp-for="Photo" class="form-control custom-file-input">
                <label class="custom-file-label">Choose File...</label>
            </div>
        </div>
    </div>

    <div asp-validation-summary="All" class="text-danger"></div>

    <div class="form-group row">
        <div class="col-sm-10">
            <button type="submit" class="btn btn-primary">Create</button>
        </div>
    </div>

    @*This script is required to display the selected file in the file upload element*@

    @section Scripts {
        <script>
            $(document).ready(function () {
                $('.custom-file-input').on("change", function () {
                    var fileName = $(this).val().split("\\").pop();
                    $(this).next('.custom-file-label').html(fileName);
                });
            });
        </script>
    }
</form>

Create Action Method

using EmployeeManagement.Models;
using EmployeeManagement.ViewModels;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using System;
using System.IO;

namespace EmployeeManagement.Controllers
{
    public class HomeController : Controller
    {
        private readonly IEmployeeRepository _employeeRepository;
        private readonly IHostingEnvironment hostingEnvironment;

        public HomeController(IEmployeeRepository employeeRepository,
                              IHostingEnvironment hostingEnvironment)
        {
            _employeeRepository = employeeRepository;
            this.hostingEnvironment = hostingEnvironment;
        }

        [HttpGet]
        public ViewResult Create()
        {
            return View();
        }

        [HttpPost]
        public IActionResult Create(EmployeeCreateViewModel model)
        {
            if (ModelState.IsValid)
            {
                string uniqueFileName = null;

                // If the Photo property on the incoming model object is not null, then the user
                // has selected an image to upload.
                if (model.Photo != null)
                {
                    // The image must be uploaded to the images folder in wwwroot
                    // To get the path of the wwwroot folder we are using the inject
                    // HostingEnvironment service provided by ASP.NET Core
                    string uploadsFolder = Path.Combine(hostingEnvironment.WebRootPath, "images");
                    // To make sure the file name is unique we are appending a new
                    // GUID value and and an underscore to the file name
                    uniqueFileName = Guid.NewGuid().ToString() + "_" + model.Photo.FileName;
                    string filePath = Path.Combine(uploadsFolder, uniqueFileName);
                    // Use CopyTo() method provided by IFormFile interface to
                    // copy the file to wwwroot/images folder
                    model.Photo.CopyTo(new FileStream(filePath, FileMode.Create));
                }

                Employee newEmployee = new Employee
                {
                    Name = model.Name,
                    Email = model.Email,
                    Department = model.Department,
                    // Store the file name in PhotoPath property of the employee object
                    // which gets saved to the Employees database table
                    PhotoPath = uniqueFileName
                };

                _employeeRepository.Add(newEmployee);
                return RedirectToAction("details", new { id = newEmployee.Id });
            }

            return View();
        }
    }
}

The rest of the code on this page is not required to upload a file. It contains code to display a specific employee details using the details view and the list of employees using the index view.

Details View Code

@model HomeDetailsViewModel

@{
    ViewBag.Title = "Employee Details";
    var photoPath = "~/images/" + (Model.Employee.PhotoPath ?? "noimage.jpg");
}

<div class="row justify-content-center m-3">
    <div class="col-sm-8">
        <div class="card">
            <div class="card-header">
                <h1>@Model.Employee.Name</h1>
            </div>

            <div class="card-body text-center">
                <img class="card-img-top" src="@photoPath" asp-append-version="true" />

                <h4>Employee ID : @Model.Employee.Id</h4>
                <h4>Email : @Model.Employee.Email</h4>
                <h4>Department : @Model.Employee.Department</h4>

            </div>
            <div class="card-footer text-center">
                <a asp-controller="home" asp-action="index" class="btn btn-primary">Back</a>
                <a href="#" class="btn btn-primary">Edit</a>
                <a href="#" class="btn btn-danger">Delete</a>
            </div>
        </div>
    </div>
</div>

Index View Code

@model IEnumerable<Employee>

@{
    ViewBag.Title = "Employee List";
}


<div class="card-deck">
    @foreach (var employee in Model)
    {
        var photoPath = "~/images/" + (employee.PhotoPath ?? "noimage.jpg");
        <div class="card m-3" style="min-width: 18rem; max-width:30.5%;">
            <div class="card-header">
                <h3>@employee.Name</h3>
            </div>

            <img class="card-img-top imageThumbnail" src="@photoPath"
                 asp-append-version="true" />

            <div class="card-footer text-center">
                <a asp-controller="home" asp-action="details" asp-route-id="@employee.Id"
                   class="btn btn-primary m-1">View</a>
                <a href="#" class="btn btn-primary m-1">Edit</a>
                <a href="#" class="btn btn-danger m-1">Delete</a>
            </div>
        </div>
    }
</div>

site.css

.imageThumbnail {
    height:200px;
    width:auto;
}

asp.net core tutorial for beginners

10 comments:

  1. all videos/blogs are very very helpful for me. thank you very much. please post advance tutorials for asp net core

    ReplyDelete
  2. Can you please tell me why in my case the ternary operator didn't worked well?

    Index.cshtml:
    @foreach (var employee in Model)
    {
    var photoPath = "~/images/" + (employee.PhotoPath ??
    "noimage.jpg");

    .
    .
    .

    And the only way to display the default photos was something like this?:
    if (!String.IsNullOrEmpty(employee.PhotoPath))
    {
    photoPath = "~/images/" + employee.PhotoPath;
    }
    else
    {
    photoPath = "~/images/noimage.jpg";
    }
    The file name was correct in both cases.

    ReplyDelete
    Replies
    1. Ternary operator doesn't have double '??'. That's your first mistake. It should be var photoPath = "~/images/" +
      employee.PhotoPath ? photoPath : "noimage.jpg";

      Delete
  3. How the detailsviewmodel is created

    ReplyDelete
  4. Sir,I am getting unauthorized access exception when i create the employee after doing this upload file process ... can you please guide me how to solve it

    ReplyDelete
  5. sir venkat thank you foor such a nice course.One thing i am not understanding the reason for using two "\\" in split method.
    var fileName = $(this).val().split("\\").pop();

    can u tell me please.

    ReplyDelete
  6. Sir, what net core version use for this example?. Thanks

    ReplyDelete
  7. Sir, I am not getting Image name on textbox when i upload image.

    private readonly IHostingEnvironment hostingEnvironment;

    public HomeController(IEmployeeRepository employeeRepository,
    IHostingEnvironment hostingEnvironment)

    ReplyDelete
  8. if your updated CSS not getting applied, try doing below:

    In in IE and FireFox I usually do Ctrl + F5 or Ctrl + Refresh button. Also you can manually clear the cache. For IE you can use the IE Dev Toolbar and for Firefox there is Firebug with both you can clear the cache easily.

    (it's happening basically because of the caching of browser.)

    ReplyDelete
  9. In my case Photo data is coming null while I am uploading one image and the file name is showing on that label. What should I do ?

    ReplyDelete

It would be great if you can help share these free resources