Suggested Videos
Part 53 - File upload in asp.net core mvc | Text | Slides
Part 54 - Upload multiple files in asp.net core mvc | Text | Slides
Part 55 - Edit view in asp.net core mvc | Text | Slides
In this video we will discuss how to handle and process the posted edit view. So in short, we want to implement Edit action that responds to HttpPost.
This is continuation to Part 55. Please watch Part 55 from ASP.NET core tutorial before proceeding.
When the following Edit view is posted to the server by clicking the Update button, we want to handle and process the posted form data.
HttpPost Edit Action
The following is the Edit action that handles the posted Edit view. The code is explained using comments where needed.
The following is the private ProcessUploadedFile() method which saves the photo in wwwroot/images folder and returns the unique file name. This file name is then assigned as the value for the PhotoPath on the employee object which will eventually be saved in the database.
Part 53 - File upload in asp.net core mvc | Text | Slides
Part 54 - Upload multiple files in asp.net core mvc | Text | Slides
Part 55 - Edit view in asp.net core mvc | Text | Slides
In this video we will discuss how to handle and process the posted edit view. So in short, we want to implement Edit action that responds to HttpPost.
This is continuation to Part 55. Please watch Part 55 from ASP.NET core tutorial before proceeding.
When the following Edit view is posted to the server by clicking the Update button, we want to handle and process the posted form data.
HttpPost Edit Action
The following is the Edit action that handles the posted Edit view. The code is explained using comments where needed.
//
Through model binding, the action method parameter
//
EmployeeEditViewModel receives the posted edit form data
[HttpPost]
public IActionResult Edit(EmployeeEditViewModel model)
{
// Check if the
provided data is valid, if not rerender the edit view
// so the user
can correct and resubmit the edit form
if (ModelState.IsValid)
{
// Retrieve the
employee being edited from the database
Employee employee =
_employeeRepository.GetEmployee(model.Id);
// Update the
employee object with the data in the model object
employee.Name = model.Name;
employee.Email = model.Email;
employee.Department = model.Department;
// If the user
wants to change the photo, a new photo will be
// uploaded and
the Photo property on the model object receives
// the uploaded
photo. If the Photo property is null, user did
// not upload a
new photo and keeps his existing photo
if (model.Photo != null)
{
// If a new photo
is uploaded, the existing photo must be
// deleted. So
check if there is an existing photo and delete
if (model.ExistingPhotoPath != null)
{
string filePath = Path.Combine(hostingEnvironment.WebRootPath,
"images",
model.ExistingPhotoPath);
System.IO.File.Delete(filePath);
}
// Save the new
photo in wwwroot/images folder and update
// PhotoPath
property of the employee object which will be
// eventually
saved in the database
employee.PhotoPath =
ProcessUploadedFile(model);
}
// Call update
method on the repository service passing it the
// employee object to update the data in the database table
Employee updatedEmployee =
_employeeRepository.Update(employee);
return RedirectToAction("index");
}
return View(model);
}
The following is the private ProcessUploadedFile() method which saves the photo in wwwroot/images folder and returns the unique file name. This file name is then assigned as the value for the PhotoPath on the employee object which will eventually be saved in the database.
private string
ProcessUploadedFile(EmployeeCreateViewModel model)
{
string uniqueFileName = null;
if (model.Photo != null)
{
string uploadsFolder = Path.Combine(hostingEnvironment.WebRootPath, "images");
uniqueFileName = Guid.NewGuid().ToString() + "_" + model.Photo.FileName;
string filePath = Path.Combine(uploadsFolder, uniqueFileName);
using (var
fileStream = new
FileStream(filePath, FileMode.Create))
{
model.Photo.CopyTo(fileStream);
}
}
return uniqueFileName;
}
Using your code above, I get these errors:
ReplyDeleteError CS1061 'EmployeeCreateViewModel' does not contain a definition for 'Photos' and no accessible extension method 'Photos' accepting a first argument of type 'EmployeeCreateViewModel' could be found (are you missing a using directive or an assembly reference?) EmployeeManagement C:\Projects\EmployeeManagement\EmployeeManagement\Controllers\HomeController.cs 137 Active
Error CS1061 'EmployeeCreateViewModel' does not contain a definition for 'Photos' and no accessible extension method 'Photos' accepting a first argument of type 'EmployeeCreateViewModel' could be found (are you missing a using directive or an assembly reference?) EmployeeManagement C:\Projects\EmployeeManagement\EmployeeManagement\Controllers\HomeController.cs 137 Active
Error CS1061 'EmployeeCreateViewModel' does not contain a definition for 'Photos' and no accessible extension method 'Photos' accepting a first argument of type 'EmployeeCreateViewModel' could be found (are you missing a using directive or an assembly reference?) EmployeeManagement C:\Projects\EmployeeManagement\EmployeeManagement\Controllers\HomeController.cs 140 Active
It doesn't seem that you are using his code above. Your code is implementing with access to selecting and uploading multiple photos while his is not. It would help if you posted the code you are using in the methods above. If you just copy pasted his code into yours then you're going to have issues with the list of photos. If you want a working version of the multiple photos version of the methods he posted above, here it is(formatting on this site isn't the greatest so make due):
Delete[HttpPost]
public IActionResult Edit(EmployeeEditViewModel model)
{
if (ModelState.IsValid)
{
Employee employee = _employeeRepository.GetEmployee(model.Id);
employee.Name = model.Name;
employee.Email = model.Email;
employee.Department = model.Department;
if (model.Photos != null)
{
if (model.ExistingPhotoPath != null)
{
string filePath = Path.Combine(hostingEnvironment.WebRootPath,
"img", model.ExistingPhotoPath);
System.IO.File.Delete(filePath);
}
employee.PhotoPath = ProcessUploadedFile(model);
}
_employeeRepository.Update(employee);
return RedirectToAction("index");
}
return View(model);
}
private string ProcessUploadedFile(EmployeeCreateViewModel model)
{
string uniqueFileName = null;
if (model.Photos != null && model.Photos.Count > 0)
{
foreach (IFormFile photo in model.Photos)
{
string uploadsFolder = Path.Combine(hostingEnvironment.WebRootPath, "img");
uniqueFileName = Guid.NewGuid().ToString() + "_" + photo.FileName;
string filePath = Path.Combine(uploadsFolder, uniqueFileName);
using(var fileStream = new FileStream(filePath, FileMode.Create))
{
photo.CopyTo(fileStream);
}
}
}
return uniqueFileName;
}
Hello sir!
ReplyDeleteThank you for your outstanding tutorial!
At this lesson I have a little observation:
If I try to replace the picture of an employee, save it and then replace again the picture for the same employee I get the following error:
IOException: The process cannot access the file 'F:\ASP Net Core Tutorial\EmployeeManagement\EmployeeManagement\wwwroot\images\87225cf0-b416-4a74-8c8a-175c1c276d2e_James.jpg' because it is being used by another process.
System.IO.FileSystem.DeleteFile(string fullPath)
System.IO.File.Delete(string path)
EmployeeManagement.Controllers.HomeController.Edit(EmployeeEditViewModel model) in HomeController.cs
+
System.IO.File.Delete(oldFielPath);
lambda_method(Closure , object , object[] )...
The file stream that copied the file at the first save is still open.
In the ProcessUploadedFile method I defined a file stream variable and call the Close() method after CopyTo():
private string ProcessUploadedFile(EmployeeCreateViewModel model)
{
string uniqueFileName = null;
if (model.Photo != null)
{
string uploadsFolder = Path.Combine(hostingEnvironment.WebRootPath, "images");
uniqueFileName = $"{Guid.NewGuid().ToString()}_{model.Photo.FileName}";
string filePath = Path.Combine(uploadsFolder, uniqueFileName);
FileStream fs = new FileStream(filePath, FileMode.Create);
model.Photo.CopyTo(fs);
fs.Close();
}
return uniqueFileName;
}
Hello, Everything was working great until I clicked on Update and got this message:
ReplyDeleteNullReferenceException: Object reference not set to an instance of an object.
AspNetCore.Views_Home_Edit.ExecuteAsync() in Edit.cshtml
Can someone please tell me what I'm missing
Hi,
ReplyDeleteI'm facing a problem: Edit action (the httppost one) always receives the ExistingPhotoPath=null, even if the view should provide it (it has an hidden input for the ExistingPhotoPath and it actually has value).
Could anyone help me please?
Thanks in advance