1

I'm working on a simple portfolio project. I would like to show images on a webpage that logged in users can edit. My problem is in the [HttpPost] Edit, more specifically this part:

if (ModelState.IsValid)
    {
      //updating current info 
      inDb = ModelFactory<ArtSCEn>.GetModel(db, artSCEn.ArtSCEnID);
      inDb.LastModified = DateTime.Now;
      inDb.TechUsed = artSCEn.TechUsed;
      inDb.DateOfCreation = artSCEn.DateOfCreation;
      inDb.Description = artSCEn.Description;
      inDb.ArtSC.LastModified = DateTime.Now;

      //validating img
      if (Validator.ValidateImage(img))
      {
           inDb.ImageString = Image.JsonSerialzeImage(img);
      }
      else
      {
          //return to the UI becuase we NEED a valid pic
           return View(artSCEn);
      }

      db.Entry(inDb).State = System.Data.Entity.EntityState.Modified;
      db.SaveChanges();

      //[PROBLEMATIC PART STARTS HERE]

      //updating the pic on the server
      //getting the string info
      string userArtImgFolder = Server.MapPath($"~/Content/Images/Artistic/{inDb.ArtSC.PersonID}");
      string imgNameOnServer = Path.Combine(
                    userArtImgFolder,
      $"{inDb.ArtSC.PersonID}_{inDb.ArtSC.ArtSCID}_{inDb.ArtSCEnID}{Path.GetExtension(img.FileName)}");


       //deleting previous pic 
       System.IO.File.Delete(imgNameOnServer);

       //creating a new pic
       Image.ResizePropotionatelyAndSave(img, Path.Combine(
                    userArtImgFolder,
                    $"{inDb.ArtSC.PersonID}_{inDb.ArtSC.ArtSCID}_{inDb.ArtSCEnID}{Path.GetExtension(img.FileName)}"));

 return RedirectToAction("Edit", "Art", new { id = inDb.ArtSCID });
            }

When I get back the new picture and I want to delete the previous, System.IO.File.Delete() always triggers an exception that it cannot access the resource, because someone else is holding onto it. Any idea what that might be? Maybe it's something simple, I'm new to ASP, but just can't figure it out.

UPDATE Following on the suggestions in the comments section, I checked the processes with a tool called Process Monitor and it seems that indeed IIS is locking the resource: Resourceenter image description here

This one appears 2 more times in the logs, by the way.

Judging by the fact that the operation is CreateFileMapping, I guess it has to do with either Server.MapPath() or Path.Combine(), however, the Server is an IDisposable (being derived from Controller), so can that be the one I should deal with?

Also, the resource I'm trying to delete is an image used on the website, which might be a problem, but that section of the website is not shown during this process.

oneManArmin
  • 606
  • 6
  • 24
  • 1
    My guess is that IIS worker process is holding a lock to your file. You can confirm the source of the lock by installing a free tool like unlockr. Anything within your code could cause IIS worker process to keep an open handle to your file, specially "Image.ResizePropotionatelyAndSave" method. I am not familiar with this method. Is this part of the standard framework or are you using a different tool? – Diablo Feb 08 '18 at 19:56
  • I give unlockr a try, thank you, althogh I don't think it is `Image.ResizePropotionatelyAndSave` (which is my own creation), because the problem persisted even when I commented that function call out. – oneManArmin Feb 09 '18 at 09:33

1 Answers1

1

I found the solution building on the comment of @Diablo.

The IIS was indeed holding on to the resource, but Server.MapPath() or any of that code had nothing to do with it: it was the Edit view my page returning the data to. With the help of this SO answer, it turns out I was careless with a BitMap that I used without a using statement in the view to get some image stats. I updated the helper function with the following code:

    public static float GetImageWidthFromPath(string imgAbsolutPath, int offset)
    {
        float width = 0;
        using (Bitmap b = new Bitmap(imgAbsolutPath))
        {
            width = b.Width - offset;
        }
        return width;
    }

Now IIS does not hold on to the resource and I can delete the file.

oneManArmin
  • 606
  • 6
  • 24