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

httppost edit action in asp.net core mvc

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 in asp.net core mvc

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;
}

asp.net core tutorial for beginners

5 comments:

  1. Using your code above, I get these errors:

    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 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

    ReplyDelete
    Replies
    1. 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):

      [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;
      }

      Delete
  2. Hello sir!
    Thank 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;
    }


    ReplyDelete
  3. Hello, Everything was working great until I clicked on Update and got this message:

    NullReferenceException: 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

    ReplyDelete
  4. Hi,
    I'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

    ReplyDelete

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