Вызов веб-службы в JavaScript вызывает белый экран смерти (WSOD) в браузере

Вот характеристики:

  • ASP.NET 3.5 с использованием ASP.NET AJAX
  • Инструментарий управления AJAX
  • jQuery 1.3.2
  • веб-сервисы
  • IIS6 на Windows Server 2003 SP1
  • SP1 SQLServer 2005 SP3 Сайт использует SSL
  • Веб-компоненты Infragistics 2009 Vol. 2 (с использованием элементов управления, не относящихся к айкидо), в основном используются элементы управления UltraWebGrid и Tree.

Вот проблема: я получаю белый экран смерти (WSOD) в IE 7/8. По сути, у меня есть страница с левой панелью, на которой есть элемент управления AJAXControl Toolkit Accordion, где содержимое каждой панели аккордеона является элементом управления деревом Infragistics. Правая панель представляет собой <div> с <iframe>, содержимое которого перезагружается в зависимости от того, что было нажато в левой панели меню.

В <iframe> страница с одним или несколькими элементами управления UltraWebGrid загружается при нажатии на элемент меню в левой панели. Все сетки имеют шаблонную колонку кнопок. При нажатии на кнопку редактирования строки сетки открывается всплывающее окно для редактирования записи. Это работает нормально примерно десять раз, а затем на десятый раз (иногда раньше) открывается всплывающее окно с правильным URL-адресом в адресной строке, но страница никогда не загружается.

У нас есть приложение, которое использует одно всплывающее окно для обновления записей. В большинстве случаев, когда вы нажимаете кнопку [Редактировать] для редактирования записи, открывается всплывающее окно и загружается страница обновления. Однако, после редактирования записей некоторое время, внезапно всплывающее окно открывается, но оно остается пустым и просто висит. URL находится в адресной строке.

Загружая Fiddler, я заметил, что запрос на страницу обновления никогда не отправляется, что наводит меня на мысль, что это какая-то блокировка на стороне клиента. Если я скопирую тот же URL-адрес, который находится во всплывающем окне, в новое окно браузера, страница обычно загружается нормально.

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

Я действительно в недоумении здесь. Я гуглил WSOD, но, похоже, мало что связано с моим конкретным WSOD. Любые идеи?

В чем проблема

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

Итак, как проще всего сделать методы веб-службы асинхронными? Нужно ли преобразовать веб-службу в веб-службу WCF или можно использовать существующий вызов веб-службы ASP.NET?

И для исторических целей, вот что я думал, что проблема изначально была:

Мне не удалось воспроизвести это локально или на наших тестовых серверах. Тем не менее, я получил Fiddler для имитации скорости модема, и внезапно я могу воспроизвести WSOD на своем локальном ПК. Таким образом, это медленное или временно медленное соединение при открытии всплывающего окна, которое заставляет его задыхаться, по крайней мере, в моей тестовой среде.

Я сделал еще один тест с запуском IE без надстроек, iexplore.exe -extoff, но в итоге получил тот же результат. Я также исправил проблему, из-за которой iframe на странице воссоздавался каждый раз при изменении URL-адреса для iframe. Часть моей логики была опущена. Теперь iframe создается только один раз. После этого только атрибут src обновляется, когда я хочу загрузить новый контент... мой дурак. Я заметил некоторые устаревшие ссылки на окна в замыканиях JavaScript, поэтому теперь они явно устанавливаются в нуль в замыканиях, когда я закончу с ними.

Я также провел некоторое расследование утечки памяти: - Насколько я могу судить, у меня нет циклических ссылок в DOM и JavaScript или других шаблонах утечки, упомянутых здесь, http://www.ibm.com/developerworks/web/library/wa-memleak/?S_TACT=105AGX52&S_CMP=cn-a-wa

  • Я добавил код очистки Crockenator от утечек памяти IE (см. http://www.crockford.com/javascript/memory/leak.html):

    $(document).ready(function() { function purge(d) { var a = d.attributes, i, l, n;

        if (a) {
            l = a.length;
    
            for (i = 0; i < l; i += 1) {
                if (a[i]) {
                    n = a[i].name;
    
                    if (typeof d[n] === 'function') {
                        d[n] = null;
                        purgeCount++;
                    }
                }
            }
        }
    
        a = d.childNodes;
    
        if (a) {
            l = a.length;
            for (i = 0; i < l; i += 1) {
                purge(d.childNodes[i]);
            }
        }        
    }        
    
    $(window).unload(function() {
      purge(document.body);
      //alert("purge count: " + purgeCount);
    });
    

    });

Ни одно из моих улучшений не решило проблему. в моем локальном тестовом сценарии. Любые идеи? Кто-нибудь? Кто-нибудь? Бьюллер?

Последнее обновление

Спасибо, Дэвид, за указание на то, что именно состояние сеанса вызывает проблемы в веб-сервисах. "ASP.NET помещает все запросы в очередь к одному и тому же "сеансу". Поэтому, если первый запрос блокируется слишком долго, он задержит любые другие запросы в очереди."

Итак, в итоге мы попытались свести к минимуму веб-сервисы, используя состояние сеанса, но мы также добавили рекомендуемые Microsoft настройки для количества подключений, см. http://msdn.microsoft.com/en-us/library/ff647786.aspx#scalenetchapt10_topic9


person nickytonline    schedule 09.06.2010    source источник


Ответы (1)


Я думаю, у вас может быть проблема с синхронизацией запроса сеанса. Пометили ли вы свои обработчики веб-служб как требующие состояния сеанса?

ASP.NET ставит в очередь все запросы к одному и тому же «сеансу». Таким образом, если первый запрос блокируется слишком долго, он задержит любые другие запросы в очереди. Вы можете отключить состояние сеанса для страницы, чтобы избежать этого и быть действительно асинхронным, однако вы не сможете получить доступ к сеансу на сервере и т. д.

Если вы используете .ashx, вам нужно использовать интерфейс для доступа к состоянию сеанса, по умолчанию он отключен, поэтому проверьте, добавили ли вы один из этих интерфейсов, и удалите, если возможно:

public class FooHandler : IHttpHandler, IReadOnlySessionState // readonly access

public class FooHandler : IHttpHandler, IRequiresSessionState // read-write access

Если вы используете страницу aspx, она включена по умолчанию, и вы должны отключить ее с помощью атрибута директивы Page:

    <%@ Page language="c#" Codebehind="WebForm1.aspx.cs"
AutoEventWireup="false" Inherits="WebApplication1.WebForm1"
EnableSessionState="false" %>
person David    schedule 15.06.2010
comment
Методы веб-службы, вызывающие проблему, используют состояние сеанса, то есть [WebMethod(EnableSession = true)]. Есть ли лучший способ получить доступ к сеансу в службе, чем через [WebMethod(EnableSession = true)]? Веб-службы, которые я запускаю, должны знать о сеансе пользователя и вызываться из JavaScript. - person nickytonline; 15.06.2010
comment
К сожалению, ASP.NET обеспечивает синхронизацию запросов для сеансов, вам придется реализовать какую-либо другую форму хранения состояния перекрестного запроса и отключить состояние сеанса в ваших веб-методах. Синхронизация запроса для состояния сеанса — вот почему вам не нужно блокировать, чтобы получить/установить из сеанса. Если вы переместите свое хранилище в пользовательский хэш в Application[], вы не получите синхронизацию запросов, но вам потребуется Application.Lock() и Application.Unlock() при доступе к этим данным. - person David; 15.06.2010
comment
Вам нужен доступ на запись к состоянию сеанса? если вы измените их на только чтение, они не будут блокировать друг друга, однако они все равно будут заблокированы любой другой страницей, которая получает блокировку записи в сеансе. См. последний раздел: msdn.microsoft.com/en-us/library/ ms178581.aspx - person David; 15.06.2010