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.
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.
Employee photo should be uploaded to wwwroot/images folder on the web server.
Employee Model Class
EmployeeCreateViewModel Class
Create View Code
The code specific to uploading the file is commented
Create Action Method
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
Index View Code
site.css
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.
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.
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;
}
all videos/blogs are very very helpful for me. thank you very much. please post advance tutorials for asp net core
ReplyDeleteCan you please tell me why in my case the ternary operator didn't worked well?
ReplyDeleteIndex.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.
Ternary operator doesn't have double '??'. That's your first mistake. It should be var photoPath = "~/images/" +
Deleteemployee.PhotoPath ? photoPath : "noimage.jpg";
How the detailsviewmodel is created
ReplyDeleteSir,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
ReplyDeletesir venkat thank you foor such a nice course.One thing i am not understanding the reason for using two "\\" in split method.
ReplyDeletevar fileName = $(this).val().split("\\").pop();
can u tell me please.
Sir, what net core version use for this example?. Thanks
ReplyDeleteSir, I am not getting Image name on textbox when i upload image.
ReplyDeleteprivate readonly IHostingEnvironment hostingEnvironment;
public HomeController(IEmployeeRepository employeeRepository,
IHostingEnvironment hostingEnvironment)
if your updated CSS not getting applied, try doing below:
ReplyDeleteIn 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.)
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