Image File sets to null after updating only other fields

asp.net-core c# entity-framework-core updating

Question

am having a weird functionality when am only updating other fields other than the image , the other fields (FirstName , LastName) update successfully but then the Image sets its self to null, but when I choose it with respect to other fields (FirstName, LastName) it updates successfully. So what I want is when I don't update the image it stays as it is without setting its self to null.

This is my New.cshtm file which handles both Creating and Editing data :

<form asp-action="New" method="Post" asp-controller="Student" enctype="multipart/form-data">
    <div asp-validation-summary="All"></div>

    <input asp-for="Id" type="hidden"/>
    <input name="IsEditMode" id="IsEditMode" value="@ViewBag.IsEditMode" type="hidden"/>


    <div class="form-row">
        <label>Upload Photo</label>
        <input asp-for="ImageUrl" type="file" id="file"  name="file" class="form-control"/>

    </div>

    <div class="form-row">
        <div class="col">
            <label asp-for="FirstName"></label>
            <input asp-for="FirstName" class="form-control"/>
            <span asp-validation-for="FirstName" class="text-danger"></span>
        </div>
        <div class="col">
            <label asp-for="MiddleName"></label>
            <input asp-for="MiddleName" class="form-control"/>
            <span asp-validation-for="MiddleName" class="text-danger"></span>
        </div>
    </div>
</form>

Then these are the methods of my controller Student.cs am using to update the fields :

public IActionResult New(Student student, string IsEditMode, IFormFile file)
        {

            if (!ModelState.IsValid)
            {
                ViewBag.IsEditMode = IsEditMode;
                return View(student);
            }

            try
            {

                if (IsEditMode.Equals("false"))
                {

                    _studentRepository.Create(student);
                     UploadFile(file, student.Id);
                    _toastNotification.AddSuccessToastMessage("Student has been created successfully.");

                }

                else
                {
                    _studentRepository.Edit(student);
                     UploadFile(file, student.Id);
                    _toastNotification.AddSuccessToastMessage("Student has been edited successfully.");

                }

                return RedirectToAction(nameof(Index));
            }
            catch (Exception e)
            {

                return RedirectToAction(nameof(Index));
            }

        }

        public IActionResult Edit(int id)
        {

            try
            {

                ViewBag.IsEditMode = "true";

                var student = _studentRepository.GetSingleStudent(id);

                return View("New", student);
            }
            catch (Exception ex)
            {
                return Content("Could not find Pet");
            }

        }

        public void UploadFile(IFormFile file, long studentId)
        {
            var fileName = file.FileName;
            var path = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot/images",fileName);

            using (var fileStream = new FileStream(path, FileMode.Create))
            {
                file.CopyTo(fileStream);
            }

            var student = _studentRepository.GetSingleStudent(studentId);
            student.ImageUrl = fileName;
            _studentRepository.Edit(student);
        }

Then, this is how I am Updating in the Repository :

Then in my Repository, this is how I am updating the fields " :

public void Edit(Student student)
        {
            var existingStudent = _context.Students

                .FirstOrDefault(s => s.Id == student.Id);

            if (existingStudent != null)
            {
                // updating student.

                _context.Entry(existingStudent).CurrentValues.SetValues(student);
                _context.Entry(existingStudent).State = EntityState.Modified;
          }
}

The Index.cshtml, this is one list the images and the First and LastName and the (action buttons) Edit, Delete buttons :

<table class="table table-striped">
        <thead class="thead-dark">
        <tr>
            <td ><b>Student Picture</b></td>
            <td><b>FirstName</b></td>
            <td><b>LastName</b></td>
            <td colspan="2"> <b>Actions</b></td>
        </tr>
        </thead>
        <tbody>
        @foreach (var student in Model)
        {
            <tr>
                <td>@student.StudentRegNo</td>
                <td>
                    <div class="thumbnail">
                        <img src="/images/@student.ImageUrl" width="90" height="90"/>
                    </div>
                </td>
                <td>@student.FirstName</td>
                <td>@student.LastName</td>
                <d>
                    <td>
                        <a class="btn btn-warning" asp-action="Details" asp-controller="Student" asp-route-Id="@student.Id">Details</a>
                    </td>
                    <td>
                        <a class="btn btn-primary" asp-action="edit" asp-route-Id="@student.Id">Edit</a>
                    </td>
                    <td>
                        <a
                            class="btn btn-danger delete"
                            asp-route-Id="@student.Id"
                            asp-action="Delete">
                            Delete
                        </a>
                    </td>
                </d>
            </tr>
        }
        </tbody>
    </table>

EDIT

This is the current logic am having according to @Raul solution, but it's not working :

if (student.ImageUrl != null)
                {
                    _context.Entry(existingStudent).CurrentValues.SetValues(student);
                    _context.Entry(existingStudent).State = EntityState.Modified;
                }

                else
                {
                    _context.Entry(existingStudent).Property(x => x.ImageUrl).IsModified = false; 
                    _context.Entry(existingStudent).CurrentValues.SetValues(student);
                    _context.Entry(existingStudent).State = EntityState.Modified;
                }

1
-1
7/17/2019 7:26:04 PM

Accepted Answer

You could consider the two scenario separately.When updating fields without updating the image, the file is null, then you need to assgin the ImageUrl of existing student to the posted student.

        //...
        try
        {
            if (IsEditMode.Equals("false"))
            {
                _studentRepository.Create(student);
                UploadFile(file, student.Id);
                _toastNotification.AddSuccessToastMessage("Student has been created successfully.");

            }
            else
            {
                //edit mode
                if(file == null)//Updating fields without updating the image.
                {
                    var existingStudent = _context.Students.FirstOrDefault(s => s.Id == student.Id);

                    if (existingStudent != null)
                    {
                        // updating student with previousImageUrl
                        student.ImageUrl = existingStudent.ImageUrl;
                        _context.Entry(existingStudent).CurrentValues.SetValues(student);
                        _context.Entry(existingStudent).State = EntityState.Modified;
                        _context.SaveChanges();
                    }
                }
                else//Updating the fields and the image
                {
                    _studentRepository.Edit(student);
                    UploadFile(file, student.Id);
                }

                _toastNotification.AddSuccessToastMessage("Student has been edited successfully.");

            }

            return RedirectToAction(nameof(Index));
        }
        catch (Exception e)
        {
            return RedirectToAction(nameof(Index));
        }
    }

    public void UploadFile(IFormFile file, long studentId)
    {
        var fileName = file.FileName;
        var path = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot/images", fileName);

        using (var fileStream = new FileStream(path, FileMode.Create))
        {
            file.CopyTo(fileStream);
        }

        var student = _studentRepository.GetSingleStudent(studentId);
        student.ImageUrl = fileName;
        _studentRepository.Edit(student);
    }

   public void Edit(Student student)
    {
        var existingStudent = _context.Students

            .FirstOrDefault(s => s.Id == student.Id);

        if (existingStudent != null)
        {
            // updating student.

            _context.Entry(existingStudent).CurrentValues.SetValues(student);
            _context.Entry(existingStudent).State = EntityState.Modified;
            _context.SaveChanges();
       }
    }
1
7/18/2019 7:01:47 AM

Popular Answer

In your Edit student method, you can set the IsModified to false for your ImageUrl Property which will not update the image field in your database:

public void Edit(Student student)
{
  var existingStudent = _context.Students.FirstOrDefault(s => s.Id == student.Id);

  if (existingStudent != null)
  {
    // updating student.
    _context.Student.Attach(existingStudent);
    _context.Entry(existingStudent).State = EntityState.Modified; 
    _context.Entry(existingStudent).Property(x => x.ImageUrl).IsModified=false; 
    _context.SaveChanges();
  }
}

Of course, you would need to check for your ImageUrl logic in this. If you get a new image then you update your model accordingly.

EDIT:

You can incorporate your if-else condidition like this:

if (student.ImageUrl != null)
{              
 _context.Student.Add(existingStudent);
 _context.Entry(existingStudent).State EntityState.Modified;
 //_context.Student.Update(existingStudent); //You can also use this. Comment out the upper two lines
 _context.SaveChanges();
}
else
{
    // updating student.
    _context.Student.Attach(existingStudent);
    _context.Entry(existingStudent).State = EntityState.Modified; 
    _context.Entry(existingStudent).Property(x => x.ImageUrl).IsModified=false; 
    _context.SaveChanges();
}


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow