7

I have a partial view on a cshtml page as follows :-

@model MvcCommons.ViewModels.CompositeViewModel

@{
ViewBag.Title = "Edit";
}

@using (Html.BeginForm()) {
@Html.ValidationSummary(true)
    <fieldset>
    <legend>Article</legend>

    @Html.HiddenFor(model => model.ArticleViewModel.Article.ArticleID)

    <div class="editor-label">
        @Html.LabelFor(model => model.ArticleViewModel.Article.CategoryID, "Category")
    </div>
    <div class="editor-field">
        @Html.DropDownListFor(model => model.ArticleViewModel.Article.CategoryID, (SelectList)ViewBag.CategoryID) 
        @Html.ValidationMessageFor(model => model.ArticleViewModel.Article.CategoryID)
    </div>

    <div class="editor-label">
        @Html.LabelFor(model => model.ArticleViewModel.Article.ArticleTitle)
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => model.ArticleViewModel.Article.ArticleTitle)
        @Html.ValidationMessageFor(model => model.ArticleViewModel.Article.ArticleTitle)
    </div>

    <div class="editor-label">
        @Html.LabelFor(model => model.ArticleViewModel.Article.ArticleDate)
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => model.ArticleViewModel.Article.ArticleDate)
        @Html.ValidationMessageFor(model => model.ArticleViewModel.Article.ArticleDate)
    </div>

        @Html.HiddenFor(model => model.PageViewModel.Page.PageTitle, new { id = "PageTitle" })
        @Html.HiddenFor(model => model.PageViewModel.Page.PageAction, new { id = "PageAction" })
        @Html.HiddenFor(model => model.ArticleViewModel.Article.ArticleID, new { id = "ArticleID" })
    <div class="ImageGallery">
        @Html.Partial("~/Views/Shared/ImageGallery.cshtml", Model)
    </div>

</fieldset>
  }

<div>
@Html.ActionLink("Back to List", "Index")

The ImageGallery.cshtml Partial View is as follows :-

@model MvcCommons.ViewModels.CompositeViewModel

@{
ViewBag.Title = "Modal image uploader";
}


<script type="text/javascript">
var pageTitle = $('#PageTitle').val();
var pageAction = $('#PageAction').val();
var id = $('#ArticleID').val();


    $(document).ready(function () {
    $('.modal_block').click(function (e) {
        $('#tn_select').empty();
        $('.modal_part').hide();
    });
    $('#modal_link').click(function (e) {
        $('.modal_part').show();
        var context = $('#tn_select').load('/Upload/UploadImage?Page=' + pageTitle + '&Action=' + pageAction + '&id=' + id, function () {
            initSelect(context);
        });
        e.preventDefault();
        return false;
    });

    $('#delete_images').click(function (e) {
        var sList = "";
        $('input[type=checkbox]').each(function () {
            var sThisVal = (this.checked ? this.value : "");
            sList += (sList == "" ? sThisVal : "," + sThisVal);
        });
        $.ajax({
            url: "/Upload/DeleteImages?IDs=" + sList + '&Page=' + pageTitle + '&Action=' + pageAction + '&id=' + id,
            data: sList,
            cache: false,
            type: "POST",
            dataType: "json"
        });

        reloadGallery();
        return false;
    });


    function reloadGallery() {
        $.ajax({
            type: "GET",
            url: '/Upload/Index/',
            data: "{}",
            cache: false,
            dataType: "html",
            success: function (data)
            { $().html(data); }

        })

    }

});

</script>

<div class="modal_block modal_part"></div>
<div class="modal_dialog modal_part" id="tn_select"></div>


<h2>List of images</h2>
<p>

    This page contains the list of all uploaded images.
</p>


@if (Model.ImageViewModel.Images.Count > 0)
{
<div class="imageContainer">

    <div class="div-table">
    <div class="div-table-row-title">
        <div class="div-table-col">Image</div>
        <div  class="div-table-col">Image Name</div>
    </div>
</div>
}
</div>
    <div class="DeleteImages">
    <a href="#" id="delete_images">Delete Selected Images.</a>
</div>    

}

else
{
<div class="imageCenter">
No images have been uploaded so far.    
</div>    
}

    <p>
<a href="#" id="modal_link">Click here to open modal dialog.</a>
</p>

<div class="clear"></div>

Here is the code in the Controller to delete the images:-

        [HttpPost]
    public ActionResult DeleteImages(string IDs)
    {
        _Page = Request.QueryString["Page"];
        _Action = Request.QueryString["Action"];
        _ItemID = Convert.ToInt32(Request.QueryString["id"]);

        Generics.PageIDS currentPage = (Generics.PageIDS)Enum.Parse(typeof(Generics.PageIDS), _Page);
        _PageID = Convert.ToInt32(currentPage);

        string[] sepImageIds = IDs.Split(',');

        foreach (string strImageId in sepImageIds)
        {
            imageViewModel.DeleteFromXML(strImageId);
        }

        return RedirectToAction(_Action, _Page, new { id = _ItemID });
    }

Everything works fine in this Partial View, except for when I delete an image, the deletion is done correctly, however when the code is passed back to the View, the Partial View is not refreshed.

Is there something I am missing?

Thanks for your help and time!

------------------UPDATE--------------------------------------------- This is the Edit Controller Action after the Delete has finished :-

        public ActionResult Edit(int id = 0)
    {
        articleViewModel.Article = unitOfWork.ArticleRepository.GetByID(id);
        pageViewModel.Page.PageTitle = "Article";
        pageViewModel.Page.PageAction = "Edit";

        if (articleViewModel.Article == null)
        {
            return HttpNotFound();
        }

        PopulateDropDownList(articleViewModel.Article.CategoryID);
        viewModel.ArticleViewModel = articleViewModel;
        int ImageCount = 0;
        imageViewModel.Images = imageViewModel.PopulateFromXML(pageViewModel.GetPageID(_PageName), id, out ImageCount).ToList();
        viewModel.ImageViewModel = imageViewModel;
        viewModel.PageViewModel = pageViewModel;

        return View(viewModel);

        //return Json(viewModel, JsonRequestBehavior.AllowGet);
    }
JMon
  • 3,387
  • 16
  • 63
  • 102
  • Check this link for "A circular reference was detected while serializing an object" error: http://blog.davebouwman.com/2011/12/08/handling-circular-references-asp-net-mvc-json-serialization/ and http://stackoverflow.com/questions/2002940/json-and-circular-reference-exception –  Sep 06 '12 at 04:45

3 Answers3

15

I think it is because all partial views are cached by default, what I would do is to create a method in the controller to return an ActionResult like so, with the output cache attribute of 0, so it does not cache

[OutputCache(Duration = 0)]
public ActionResult ImageGalleryAction()
{
  // do return your cshtml name here
  return PartialView("ImageGallery");
}

I would give an id to your imageGalleryDiv, change your reloadGallery method to load the partial view on onload event as well and remove the @Html.Partial like so

<script>
function reloadGallery(){
   $('#myImageGallery').load("ImageGalleryAction");
}
</script>

<div id="myImageGallery" class="ImageGallery" onload="reloadGallery()">
 </div>

That way, your partial view will be manually injected/refreshed via jquery and it won't be cached.

Cheers

Joshscorp
  • 1,832
  • 4
  • 22
  • 42
0

You need to call the reloadGallery function once your DELETE ajax call succeeds, which is inside the success callback:

$.ajax({
    url: '/Upload/DeleteImages?IDs=' + sList + '&Page=' + pageTitle + '&Action=' + pageAction + '&id=' + id,
    data: sList,
    cache: false,
    type: 'POST',
    success: function(data) {
        reloadGallery(); 
    }        
});

Not to mention that your DeleteImages action doesn't return any JSON, so you should remove the dataType: 'json' switch. You seem to be redirecting at the end of the DeleteImages action. Are you sure that you are redirecting to a controller action that returns a partial?

Also instead of firing yet another AJAX request in your reloadGallery method why not simply have your DeleteImages action return the partial and inside the success call update the corresponding section of your DOM using the .html method?

Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • still not working. I have updated my question with the Edit Action. The problem is when I turn it to JsonResult, I get the following error :- "A circular reference was detected while serializing an object of type 'System.Data.Entity.DynamicProxies.Article_322E395367D2F518BE04DF9958A812ADE748C28C1CE68839C77009304DFAE34C'." – JMon Aug 28 '12 at 07:25
  • You need to use view models, you cannot JSON serialize objects with circular references. – Darin Dimitrov Aug 28 '12 at 07:29
  • I am using ViewModels, I am returning a CompositeViewModel – JMon Aug 28 '12 at 07:32
  • You must get rid of all possible circular references that you might have in this view model. For example if you have a property in this view model in which you have directly stored your domain model then this might be the problem. View models should not have any references to domain models. – Darin Dimitrov Aug 28 '12 at 07:44
  • Darin I am new to all this MVC and Jquery thing. What do you mean by domain model? Is it the model that I am getting the View Model from? For example I have an Image Model, and then an Image ViewModel that is "inheriting" the Image from. Is that bad for circular reference? I also have a CompositeViewModel, and I am instantiating 4 ViewModels in it. Is that bad coding? I needed to have a reference for the Page, Image and Article in the View, that is why I created the Composite ViewModel – JMon Aug 28 '12 at 08:00
  • Ok I have removed the lazy loading cause that seems to have been causing the circular reference, however now, I am getting a long string instead of the proper view when returning the JsonResults – JMon Aug 28 '12 at 08:26
0

I think it might be in your ajax call

function reloadGallery() {
    $.ajax({
        type: "GET",
        url: '/Upload/Index/',
        data: "{}",
        cache: false,
        dataType: "html",
        success: function (data)
        { $().html(data); }

    })

}

remove the data: "{}" or replace it with data: {}

feskr
  • 759
  • 6
  • 10