如何阻止浏览器后退按钮显示我的用户通知?

时间:2011-08-03 22:06:19

标签: javascript asp.net-mvc-3 notifications browser-cache

我已经为我一直在努力的ASP.NET MVC3网站构建了一个通知系统,让用户知道他们执行的各种操作成功发生了(“拍拍背”消息)。解决方案非常有效,但我有一个问题需要解决,但我似乎无法解决这个问题。

在控制器中,我有以下示例操作方法:

<HttpGet()>
Public Function Edit(id As Guid) As ActionResult
    Return View(GetMyViewModel(id))
End Function

<HttpPost()>
Public Function Edit(...) As ActionResult
    ' Save updated ... information

    Me.TempData("UserMessage") = "Data Saved! You are truly an awesome user!"

    ' PRG back to Edit
    Return RedirectToAction("Edit")
End Function

然后在我看来(razor布局)我有代码在"UserMessage"集合中寻找TempData密钥的存在,如果它存在,我构建了一些JavaScript来呈现一个咆哮 - 喜欢用户的通知:

/* This only exists when we have something to show */
$(function () {
    showNotification([the message from TempData]); 
});

随着时间的推移,类似咆哮的消息要么消失,要么用户可以点击消息来消除它。

到目前为止,一切都按预期工作。用户发送到Edit的帖子,它们被重新标记为Edit,类似咆哮的“数据已保存!您真是一个非常棒的用户!”消息会被显示和解除。< / p>

如果用户然后导航到另一个页面,然后点击浏览器的后退按钮,则浏览器会深入其缓存,导致浏览器执行相同的javascript,向用户显示相同的“数据保存!您是真的是一个很棒的用户!“再次发送消息。这让用户感到困惑,认为通过点击后退按钮,他们只是做了一些导致又一次保存的事情(或者无论消息是什么)。

我正在寻找一种方法,一旦通知显示一次,我可以以某种方式阻止通知显示备份 - 基本上使其成为“一次性”镜头消息。我想到的是:

  • 在每条消息中包含Guid,并使用localStorage存储显示的消息ID列表,并且只有在显示的消息列表中尚未存在请求的消息时,才显示它。
    • 我曾想过以同样的方式使用Cookie,但是为了将来的请求不必要地将cookie重新发送到服务器,以及需要仔细考虑cookie的内容并且可能需要 - 无论如何消息。
  • 不是从操作方法返回消息,而是返回Guid而不是指向数据库中的消息。然后在页面加载时,AJAX返回服务器以获取该消息。获取消息后,将从数据库中删除该消息,通过不返回任何消息来处理对该消息的后续请求。
  • 在每条消息中包含Guid,在显示消息之前,AJAX返回服务器以查看消息是否已显示。显示消息后,AJAX将返回服务器以记录消息已显示。

这些对我来说似乎都是站不住脚的,但如果有人想争辩支持其中一个,我可能会相信。

我尝试过的事情:

  • 解除消息后删除DOM元素的所有痕迹。
  • 显示消息时,在消息的DOM元素上设置jQuery .data()属性以指示消息已显示,然后在显示消息之前,确保.data()字段不存在

这些不起作用,因为浏览器会在之后发生这两个DOM更改的时间点缓存页面。

基本上,我需要一种机制,我的javascript可以查看它是否真的需要显示这条给定的消息,如果确实如此,请显示它,然后将消息标记为如图所示,以便在请求显示时再一次,它没有。有什么建议吗?

3 个答案:

答案 0 :(得分:2)

您还可以利用浏览器记住表单值的事实,简单示例:

<input id="notification" style="display:none" value="Data Saved!">
<script  type="text/javascript">
$(function () {
    if($('#notification').val())
    {
      alert($('#notification').val());
      $('#notification').val('');
    }
});
</script>

答案 1 :(得分:1)

您可以设置cookie来存储正在显示的消息的状态,并在您尝试显示消息时检查cookie是否存在。如果cookie在那里,你不会,如果不是,你就这样做 似乎逻辑非常简单,而不是跟踪GUID :)

// pseudocode
FUNCTION ShowMessage(args)
    // if the cookie is here, don't show the message
    IF StatusCookieIsPresent THEN RETURN

    // if the cookie isn't here, this is the first time showing the message
    ShowStatusMessage()

    // we showed the message, so set the cookie to make sure we don't
    // do it twice
    SetStatusCookie()
END FUNCTION

答案 2 :(得分:1)

我不是MVC的专家,但我会尽力帮助你。我3年前制作了一个Hello World计划,并阅读了很多相关内容。 :-)你在你的页面中使用AJAX历史记录(在查询字符串中使用#符号 - 雅虎打破了他们新的YUI邮件框架的功能,或忘记了当你点击后退按钮时 - 发送到登录页面哈哈)?当您单击后退按钮时,您是来自不同的页面还是同一页面来显示您的消息?我不太了解Razor框架可以完全帮助你。

起初我以为你可以通过使用这个代码轻松地在页面上禁用缓存,但后来我发现你正在使用AJAX,所以这可能不是一个足够好的解决方案。

<META HTTP-EQUIV="CACHE-CONTROL" CONTENT="NO-CACHE">
<META HTTP-EQUIV="EXPIRES" CONTENT="0">
<META HTTP-EQUIV="PRAGMA" CONTENT="NO-CACHE">

这会完全关闭它,但出于性能原因可能不是一个好的解决方案。

<caching>
  <outputCache enableOutputCache="false" />
</caching>

您可以阻止显示收藏中用户消息的页面的缓存,但我不知道您的AJAX中发生了什么以确定。

Response.CacheControl = "No-Cache"

不确定MVC是否会尊重这一点,但值得一试:

Response.Cache.SetExpires(DateTime.Now.AddSeconds(60));
Response.Cache.SetCacheability(HttpCacheability.Public);
Response.Cache.SetValidUntilExpires(false);
Response.Cache.VaryByParams["Category"] = true;

if (Response.Cache.VaryByParams["Category"])
{
   //...
}

或者,也许那个页面是填充中间的甜甜圈,它太满了(对于浏览器后退按钮) - 没有双关语意图。把它变成甜甜圈,它可以解决你的问题。基本上,您可以实现包含您显示的消息的视图控件。并从此视图控件中删除缓存策略。我想它会在理论上起作用。希望它在现实生活中很适合你。

http://haacked.com/archive/2009/05/12/donut-hole-caching.aspx

OutputCache属性(在该文章中提到)仅控制给定用户控件的缓存。

http://msdn.microsoft.com/en-us/library/hdxfb6cy.aspx