как молча гарантировать выполнение действия ASP.NET MVC3 при выгрузке страницы - PullRequest
1 голос
/ 24 октября 2011

Мне нужно выполнить действие контроллера, когда пользователь покидает страницу (закрыть, обновить, перейти по ссылке и т. Д.). Код действия выглядит так:

public ActionResult WindowUnload(int token)
    {
        MyObjects[token].Dispose();
        return Content("Disposed");
    }

При загрузке окна я делаю Ajax запрос к действию:

$(window).unload(function ()
{
    $.ajax({
        type: "POST",
        url: "@Url.Action("WindowUnload")",
        data: {token: "@ViewData["Token"]"},
        cache: false,
        async: true
    });
    //alert("Disposing.");
})

Вышеуказанный запрос ajax не приходит на мой контроллер, т.е. действие не выполняется. Чтобы приведенный выше код работал, мне нужно раскомментировать строку alert, но я не хочу оповещать пользователя.

Если я изменю параметр async на false (комментируется alert), то иногда он работает. Например, если я обновлю страницу несколько раз слишком быстро, то действие не будет выполняться при каждой выгрузке.

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

Обновлено: резюме ответов

Невозможно надежно выполнить запрос при выгрузке, так как он не является правильным или ожидаемым поведением при выгрузке. Поэтому лучше перепроектировать приложение и избегать выполнения HTTP-запроса при выгрузке окна. Если этого не избежать, то есть общие решения (описанные в вопросе):

  1. Звоните ajax синхронно, т.е. async: false.
    • Плюсы: в большинстве случаев работает.
    • Плюсы: тихий
    • Минусы: не работает в некоторых случаях, например, когда пользователь обновляет окна в несколько раз слишком быстро (наблюдается в Firefox)
  2. Используйте alert на success или после ajax вызова
    • Плюсы: похоже, работает во всех случаях.
    • Минусы: не тихий и всплывающие оповещения.

Ответы [ 7 ]

3 голосов
/ 24 октября 2011

HTTP не имеет состояния, и вы никогда не сможете получить надежный способ определить, что пользователь покинул вашу страницу.

Рекомендуемые события:

  • Тайм-аут сеанса (если вы используете сеансы)
  • Приложение закрывается
  • Таймер (необходимо объединить с предыдущим предложением)
  • Удалить предыдущий токен при посещении новой страницы.
3 голосов
/ 24 октября 2011

Согласно документации unload, с async: false он должен работать как положено. Тем не менее, это всегда будет немного шатко - например, пользователь может покинуть вашу страницу, убив / сбив браузер, и вы не получите никакого обратного вызова. Кроме того, реализации браузера варьируются. Боюсь, что вы не получите даже отказоустойчивых.

1 голос
/ 24 октября 2011

Из вашего комментария к ответу @ Frazzell кажется, что вы пытаетесь управлять параллелизмом.Таким образом, на случай, если это так, вот два распространенных метода управления им:

Оптимистичный параллелизм

Оптимистичный параллелизм добавляет временную метку к таблице.Когда клиент редактирует запись, отметка времени включается в форму.Когда они публикуют свое обновление, отправляется также отметка времени, и проверяется значение, чтобы убедиться, что оно самое последнее в таблице.Если это так, обновление выполнено успешно.Если это не так, то кто-то другой пришел раньше с обновлением, поэтому он будет удален.То, как вы справитесь с этим, зависит от вас.

Пессимистический параллелизм

Если вы часто сталкиваетесь с конфликтами параллелизма, тогда пессимистический параллелизм может быть лучше.Здесь, когда клиент редактирует запись, в этой строке устанавливается флаг для ее блокировки.Это будет оставаться до тех пор, пока клиент не завершит редактирование, и никакой другой пользователь не сможет редактировать эту строку.Этот метод предотвращает потерю изменений пользователями, но добавляет администрирование над приложением.Теперь вам нужен способ освободить нежелательные блокировки.Вы также должны сообщить пользователю через пользовательский интерфейс, что строка заблокирована для редактирования.

По моему опыту, лучше начать с оптимистичного параллелизма.Если у меня будет много людей, сообщающих о проблемах, я постараюсь выяснить, почему у людей возникают такие конфликты.Возможно, мне придется разбить некоторые объекты на более мелкие типы, поскольку они стали ответственными за выполнение слишком большого количества заданий.

1 голос
/ 24 октября 2011

Почему это вообще должно происходить?

Из фрагмента кода, который вы разместили, вы пытаетесь использовать его для удаления объектов на стороне сервера? Вы должны вызывать Dispose для освобождения любых неуправляемых ресурсов , которые используют ваши объекты (например, соединения с базой данных).

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

Если вы пытаетесь сделать это так, как указано выше, код необходимо переработать.

1 голос
/ 24 октября 2011

Вы пробовали onbeforeunload () ?

$(window).bind('beforeunload', function() 
    { 
        alert('unloading!'); 
    } 
);

или

window.onbeforeunload = function() {
    alert('unloading!'); 
}
0 голосов
/ 24 октября 2011

Вы не можете.Единственное, что вы можете сделать, это побудить пользователя остаться и надеяться на лучшее.Здесь есть целый ряд проблем безопасности.

0 голосов
/ 24 октября 2011

Это не сработает, и даже если вам удастся как-то заставить его работать, это впоследствии доставит вам много головной боли, потому что это не то, как предполагается использовать браузер / HTTP.Когда страница выгружается (в браузере), браузер вызывает событие unload, а затем выгружает страницу (вы не можете заставить ее ждать, даже если я выполняю синхронизацию вызовов ajax), и в случае, если вызов продолжался, и браузер после выполненияКод выгрузит страницу, вызов также будет отменен, поэтому иногда вы видите вызов на сервере, а иногда он не работает.Если бы вы могли сказать, почему вы хотите это сделать, мы могли бы предложить вам лучший подход.

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