Question

My situation is this:

I have this ViewModel:

public class RealtyViewModel
{
     public RealtyViewModel()
     {
          Realty = new Realty();
          Photos = new Collection<File>();
     }

     public Realty Realty { get; set; }

     public Collection<File> Photos { get; set; }
}

I pass this RealtyViewModel to my Edit.cshtml view. Inside the Edit view I call a Photos.cshtml partial view. The Photos partial view also uses the same @model RealtyViewModel.

Now, inside the Photos.cshtml partial view I do an AJAX request to delete a photo:

@Ajax.ImageActionLink
(@Url.Content(Model.Photos[i].Path), @Localization.Delete, "640", "480",
"DeletePhoto", new {realtyId = Model.Realty.Id, photoId = Model.Photos[i].Id},
new AjaxOptions()
                 {
                      Confirm = @Localization.DeleteConfirmation,
                      HttpMethod = HttpVerbs.Post.ToString(),
                      OnComplete = string.Format("deletePhotoFromPage('{0}')",
                                                                  Model.Photos[i].Id),
                      OnSuccess = "LoadCycle",
                      UpdateTargetId = "myDiv",
                      InsertionMode = InsertionMode.Replace

                 }, new {data_photoId = Model.Photos[i].Id})

I run this code:

[HttpDelete]
public ActionResult DeletePhoto(string realtyId, string photoId)
{
    Realty realty = DocumentSession.Load<Realty>(realtyId);

    realty.Photos.Remove(photoId);

    File photo = DocumentSession.Load<File>(photoId);

    // Deletes the file in the database
    DocumentSession.Advanced.DatabaseCommands.Delete(photoId, null);

    // Deletes the file in the disk
    System.IO.File.Delete(Server.MapPath(photo.Path));

    return new EmptyResult();
}

The problem is: my current realtyViewModel that I passed to the Edit view still references the photos I have deleted using the AJAX calls. Then when I try to save an updated model, it saves everything again holding the old references to the photos I have just deleted.

How can I update my model ( remove the deleted photos from [ model.Realty.Photos ] ) so that it reflects the current state of my Edit view?

Note: now it's working because I'm using the Session object to store the Ids of deleted photos, but it's not the way I think it should be. There must be a beautiful solution to this that just doesn't come to my mind...

A beautiful solution would be: after a success deletion, the Ajax call should return the deleted photo Id so that I could remove it from [ model.Realty.Photos ]. Then, when I tried to save an edited Realty, it would reflect the changes correctly.

Was it helpful?

Solution

After a discussion on chat it seems that you have hidden fields in your DOM that you need to remove:

@for (int i = 0; i < Model.Realty.Photos.Count(); i++)
{
    @Html.HiddenFor(
        m => m.Realty.Photos[i], 
        new { data_photoid = Model.Realty.Photos[i] }
    )
}

Now you could have your controller action return the id of the photo that has to be deleted using JSON for example instead of an empty result:

[HttpDelete]
public ActionResult DeletePhoto(string realtyId, string photoId)
{
    ... 
    return Json(new { photoId = photoId });
}

and on the client:

function deletePhotoFromPage(result) { 
    ...
    $(':hidden[data-photoid="' + result.photoId + '"]').remove(); 
}

and also you should use the OnSuccess option instead of OnComplete in your Ajax link options:

OnSuccess = "deletePhotoFromPage"

instead of:

OnComplete = string.Format("deletePhotoFromPage('{0}')", Model.Photos[i].Id),

OnComplete could be invoked even in case of error.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top