.NET MVC 缓存、Chrome、具有可变结果的操作和 HTML5 历史 API

.NET MVC Cache, Chrome, Actions with Variable Results, and the HTML5 history API

我的 .NET MVC 控制器中有一些操作可以 return 常规请求的完整视图,但如果请求是 Ajax 请求,则只有部分视图。

控制器动作结束时...

    if (HttpContext.Request.IsAjaxRequest())
    {
        return PartialView("_Partial", model);
    }
    else
    {
        return View(model);
    }

在同一个控制器上,我设置了一些缓存选项,这样一个结果应该为 ajax 请求缓存,一个结果为常规请求缓存。

[OutputCache(Duration = 120, VaryByParam = "*", VaryByHeader="X-Requested-With")]

最后,我使用 history.pushState and the onpopstate 事件控制历史记录,这样如果用户单击 "back" 按钮,只有页面中发生变化的部分会被重新加载。

jQuery(document).ready(function () {
    if (history.pushState) {
        $(window).on("popstate", function (e) {
            FunctionThatUsesAjaxToRewriteThePage();
        });
    }

    $('#SomeForm').on('submit', function (e) {
        e.preventDefault();
        var url = FunctionToGetUrlToUse();
        if (history.pushState) {
            history.pushState(null, null, url);
            FunctionThatUsesAjaxToRewriteThePage();
        }
        else {
            window.location.href = url;
        }
    });
});

除 Google Chrome 外,这工作正常。有时,当我通过浏览器的后退和前进按钮导航到页面时,Chrome 会不恰当地呈现 AJAX return 值而不是整个页面。

到目前为止,这似乎只有在我使用 back/forward 按钮导航到另一个页面(我的 MVC 站点上的另一个操作,或者我域中的另一个站点)然后 return 使用后退或前进按钮转到违规操作。详细导航步骤:

  1. 我加载我网站的主页 (http://mysite.co)。
  2. 我在主页上单击一个 link 到使用所有 Ajax/history API 魔法 (http://mysite.co/month/2016/december) 的控制器操作。
  3. 我在该页面中单击了 link,触发了主页内容的 ajax 重写 (http://mysite.co/month/2016/january)。
  4. 我单击返回(触发 popstate 事件,URL 更改为 http://mysite.co/month/2016/december 并且 Ajax 重写函数被调用)。
  5. 我再次点击返回(回到http://mysite.co)。
  6. 我点击前进。这 return 将我引导至 http://mysite.co/month/2016/december,但我只获得了 ajax 版本的操作,而不是整个页面,这只是部分视图。

Firefox 和 IE 没有这种错误行为。

我试图解决的事情:

  1. 仅将输出缓存位置指定为服务器。即使在 Chrome 中清除缓存后,我仍然会在不应该的时候得到页面的 AJAX 版本。

[OutputCache(Duration = 120, VaryByParam = "*", VaryByHeader="X-Requested-With", Location=OutputCacheLocation.Server)]

  1. 将更多 standard/serializable 个对象提供给 history.pushState

history.pushState({}, '', url); 要么 history.pushState({id: "foo"}, '', url);

  1. 根据 HTML5 History API: JSON displayed when going "back" to another page, and then "forward" again.

    向 ajax 请求添加任意参数
    $.ajax
    ({
        url: url,
        type: 'GET',
        traditional: true,
        contentType: 'application/json',
        data: {
            //all my normal URL parameters go here
            ajax: "true"
        },
      //.....
    

没关系!实际上我尝试的第三件事(向 AJAX 请求添加一个虚拟参数)确实有效,但是我需要清除我的缓存在 Chrome 之前我会看到结果。

简而言之,这样做:

    $.ajax
    ({
        //...
        data: {
            //...your data here
            ajax: "true" //Add this line or one like it to differentiate AJAX requests
        },

然后 然后 清除 Chrome 中的缓存(Ctrl+Shift+Del 用于 Windows 或 Shift+Command+Del 用于 Mac).