6

I have a partial view which is being loaded into an jQuery modal in asp.net MVC 3. The problem is that the view is not refreshing properly. Here is the order of events:

1) The main view has a table listing different events records. There is a link on each row of the table to show the event detail. 2) When the link on this table is clicked, the partial view is loaded in the modal.

This works fine in some cases, in other cases the model will take very long to load. After closing the partial view/modal and clicking on another link from the table on the main view, the partial view will load showing the data from the previous load. It is not refreshing correctly.

Definition of Modal on Main View: Loading, please wait...

<script type="text/javascript">
    $(document).ready(function () {
        $("#EventRegistrantSummary").dialog({
            bgiframe: true, autoOpen: false, height: 500, width: 980, resizable: false, modal: true
        });
    });
    function showEventRegistrantSummary(id) {
        $.get("/Event/EventRegistrantSummary/" + id, function (data) {
            $("#EventRegistrantSummary").html(data);
        });
        $("#EventRegistrantSummary").dialog('open'); return false;
    }
</script>

Controller:

    public PartialViewResult EventRegistrantSummary(Guid id)
    {
        ModelState.Clear();
        Event e = db.Events.Single(ev => ev.ID == id);
        return PartialView(e);
    }

Partial View:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<model.Event>" %>
<% using (Ajax.BeginForm("EditUpdate", new AjaxOptions { UpdateTargetId="Target", InsertionMode= InsertionMode.Replace}))
       {%>

       <h6 style="text-align:center">Registration Summary: <%= Model.Name %></h6>

       <div style="float:left;width:35%">
            <fieldset id="Overview">
                <legend>Overview</legend>
                <div class="editor-label">
                    Total Registrants: <%= Model.BoatEventRegistrations.Count() %>
                </div>
            </fieldset>
           </div>
    <% } %>

Any help is much appreciated.

NateReid
  • 206
  • 1
  • 2
  • 6

3 Answers3

8

Use the OutputCacheAttribute on your controller action to disable caching.

[OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")]
public PartialViewResult EventRegistrantSummary(Guid id)
{
    ModelState.Clear();
    Event e = db.Events.Single(ev => ev.ID == id);
    return PartialView(e);
}
jgauffin
  • 99,844
  • 45
  • 235
  • 372
  • Had no idea you could do that, always used jQuerys cache option / add a random number on the end. Not usefull for the current way we do things but very good to know. +1. – Henry Aug 11 '11 at 14:54
  • 1
    Thanks for the suggestion. I tried this option on the controller but as soon as I click on the next event/link the modal screen (partial view) loads showing the event/link details I viewed previously. – NateReid Aug 18 '11 at 13:34
  • 1
    Thank you very much! Wish I had googled for this earlier instead of spending an hour trying to debug this issue! – Greg Quinn Jul 06 '13 at 07:54
  • 2
    Thanks a million jgauffin... this helped me and my programming peer solve a nasty bug regarding a `PartialView` being returned in a `POST` action. `ModelState.Clear()` was very important. Doing only the `OutputCache` part was not sufficient. – Leniel Maccaferri Aug 28 '13 at 02:33
  • I just wrote a blog post showing a use case where your answer can save the developer's butt :D: http://www.leniel.net/2013/09/detecting-fixing-ajax-beginform-partial-view-stale-data.html – Leniel Maccaferri Sep 13 '13 at 15:11
5

Sounds like a caching issue. GET requests could be cached by some browsers. Try replacing the $.get AJAX call by a $.ajax by setting cache: false or try a $.post request:

$.ajax({
    url: '<%= Url.Action("EventRegistrantSummary", "Event") %>',
    type: 'GET',
    cache: false,
    data: { id: id },
    success: function(data) {
        $('#EventRegistrantSummary').html(data);
    }
});

Also you don't need clearing the ModelState in your EventRegistrantSummary action as you are not modifying any of the values.

Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • Are you aware of any benefits to using this method vs controlling caching at the server by using the `OutputCacheAttribute` on the controller? – Brian Cauthon Aug 11 '11 at 14:56
  • If you use a shared ajax call for multiple actions or have a lot of methods that need to avoid the cache. We handle around 95% of all form posts via jQuery due to the control given. – Henry Aug 11 '11 at 14:59
0

Another approach is to attatch a random number to the query string as you are using the in build MVC helpers.

For example:

@Ajax.ActionLink("LinkText", "Index", "Home", new { rnd = DateTime.Now.Ticks }, new AjaxOptions { UpdateTargetId = "main", OnSuccess = "pageloadSuccess" })

Or for a form:

using (Ajax.BeginForm("EditUpdate", new { rnd = DateTime.Now.Ticks }, new AjaxOptions { UpdateTargetId="Target", InsertionMode= InsertionMode.Replace}))

Not always the best way to do things but if you want to avoid tagging each of your methods (If you have alot that need to avoid cache problems) or using jQuery to handle the submission yourself this is a quick work around.

Henry
  • 2,187
  • 1
  • 15
  • 28