Как я могу запретить браузеру кнопку «Назад» повторно отображать мое уведомление пользователя? - PullRequest
5 голосов
/ 04 августа 2011

Я создал систему уведомлений для сайта 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

Затем, на мой взгляд (макет бритвы), у меня есть код, который ищет наличие ключа "UserMessage" в коллекции TempData, и, если он существует, я создаю некоторый JavaScript, чтобы представить похожее на рычание уведомление для пользователь:

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

Сообщение, похожее на рычание, либо со временем уходит, либо пользователь может щелкнуть сообщение, чтобы отклонить его.

Пока все хорошо, все работает как положено. Пользователь отправляет на Edit, они возвращаются к Edit, похожему на рычание " Данные сохранены! Вы действительно потрясающий пользователь! " сообщение показывается и отклоняется.

Если пользователь затем переходит на другую страницу и затем нажимает кнопку «Назад» браузера, браузер копает в свой кэш, в результате чего браузер выполняет тот же JavaScript, показывая пользователю тот же « Данные сохранены! действительно потрясающий пользователь!"сообщение снова. Это приводит в замешательство пользователя, который думает, что, нажав кнопку «назад», он просто сделал что-то, что вызвало еще одно сохранение (или какое-либо другое сообщение).

Я ищу способ, чтобы, когда уведомление показывалось один раз, я мог как-то предотвратить его повторное отображение - по сути, делая его "одноразовым" сообщением. Вещи, о которых я думал:

  • включая Guid с каждым сообщением и использование localStorage для хранения списка отображаемых идентификаторов сообщений, и только если запрашиваемое сообщение еще не существует в списке отображаемых сообщений, показывайте его.
    • Я думал об использовании Cookie таким же образом, но не согласился с мыслью, что cookie бесполезно отправляется обратно на сервер для будущих запросов, плюс необходимо тщательно изучить содержимое cookie и, вероятно, сообщение в любом случае.
  • Вместо того, чтобы возвращать сообщение из метода действия, вместо него возвращается Guid, который указывает на сообщение в базе данных. Затем при загрузке страницы AJAX возвращается на сервер, чтобы получить это сообщение. Как только сообщение получено, оно удаляется из базы данных, последующие запросы для этого же сообщения обрабатываются без возврата сообщения.
  • включает Guid с каждым сообщением, и перед отображением сообщения AJAX возвращается на сервер, чтобы проверить, было ли уже показано сообщение. Как только появится сообщение, AJAX вернется на сервер, чтобы записать, что сообщение было показано.

Все это кажется мне довольно несостоятельным, но я мог бы быть уверен, что если кто-то захочет спорить о поддержке одного из них.

Вещи, которые я пробовал:

  • После закрытия сообщения удаляются все следы элемента DOM.
  • Когда сообщение отображается, задайте свойство jQuery .data() в элементе DOM сообщения, чтобы указать, что сообщение было показано, а затем, прежде чем показывать сообщение, убедитесь, что поле .data() не существует.

Они не работают, потому что браузер кэширует страницы в тот момент времени, когда оба этих изменения DOM происходят позже.

По сути, мне нужен механизм, который мой javascript может проверить, действительно ли ему нужно показывать данное сообщение, и если да, то показать его, но затем пометить сообщение, как показано, чтобы, если его просят показать опять же, это не так. Есть предложения?

Ответы [ 3 ]

2 голосов
/ 04 августа 2011

Вы также можете воспользоваться тем, что браузеры запоминают значения форм, простой пример:

<input id="notification" style="display:none" value="Data Saved!">
<script  type="text/javascript">
$(function () {
    if($('#notification').val())
    {
      alert($('#notification').val());
      $('#notification').val('');
    }
});
</script>
1 голос
/ 06 августа 2011

Я не эксперт в MVC, но я постараюсь помочь вам.Я сделал программу Hello World 3 года назад и много о ней читал.:-) Используете ли вы историю AJAX на своей странице (используя нотацию # в строке запроса - функциональность, которую Yahoo сломал со своей новой почтовой структурой 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"])
{
   //...
}

Или,может быть, эта страница - пончик с начинкой посередине, и она слишком заполнена (для кнопки возврата браузера) - каламбур не предназначен.Сделайте это пончик дырой, и это может решить вашу проблему.По сути, вы могли бы реализовать элемент управления view, который содержит отображаемое вами сообщение.И удалите политику кэширования из этого представления управления.Я полагаю, это будет работать в теории.Надеемся, что в реальной жизни он хорошо работает для вас.

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

Атрибут OutputCache (упомянутый в этой статье) просто контролирует кэш для данного пользовательского элемента управления.

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

1 голос
/ 04 августа 2011

Вы можете установить 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...