views:

97

answers:

1

Here's the specs:

  • ASP.NET 3.5 using ASP.NET AJAX
  • AJAX Control Toolkit
  • jQuery 1.3.2
  • web services
  • IIS6 on Windows Server 2003 SP1
  • SP1 SQLServer 2005 SP3 Site is SSL
  • Infragistics Web Components 2009 Vol. 2 (using non-Aikido controls), UltraWebGrid and Tree control are main ones used.

Here's the problem: I'm getting the White Screen of Death (WSOD) in IE 7/8. Basically, I have a page that has a left pane that has an AJAXControl Toolkit Accordion control where each accordion panes content is an Infragistics Tree Control. The right pane is a <div> that has an <iframe> whose content is reloaded based on what's clicked in the left menu pane.

In the <iframe>, a page with one or more UltraWebGrid controls loads up when you click on a menu item in the left pane. The grids all havea templated button column. When you click on the edit button of a grid row a popup window to edit the record is opened. This works fine for about ten times and then on the tenth time (sometimes earlier), the popup window opens with the correct URL in the address bar, but the page never loads.

We have an application that uses one popup window for updating records. Most of the time when you click on the [Edit] button to edit a record, the popup window opens and loads the update page. However, after editing records for a while, all of a sudden the popup window will open, but it stays blank and just hangs. The URL is in the address bar.

Loading up Fiddler I noticed that the request for the update page is never sent which leads me to believe it's some kind of lockup on the client-side. If I copy the same URL that's in the popup window into a new browser window, the page generally loads fine.

Observations: - Since the request is never sent to the server, it's definitely something client-side or browser related. - Only appears to happen when there is some semblance of traffic on the site which is weird because this appears to be contained within client-side code - There is a web service being called in the background every few seconds checking if the user is logged on, but this doesn't cause the freeze.

I'm really at a loss here. I've googled WSOD but not much seems to appear related to my specific WSOD. Any ideas?

What the problem really is

So turns out the memory leaks (although I've sealed up some on the client-side) are not the issue. The issue is web service calls being made on the client-side. There is one that checks if a user is logged on every 4 seconds (to synchronize with another window) and then there are web service calls to get user preferences for a popup window and grid state. From what I've read, the web services have to be asynchronous. I assumed by calling them from JavaScript with success/fail callbacks that they were asynchronous but they really aren't. They're asynchronous from the client-side/browser point of view, but from the server-side, the call to the web service is made and returns when it is completed holding up any other operations since there is a limited number of connections.

So what is the easiest way to just make the web service methods asynchronous? Does the web service need to be converted to a WCF web service or can I use my existing ASP.NET web service call?

And for historical purposes, here's what I thought the problem was originally:

I wasn't able to reproduce this locally or on our testing servers. However, I got Fiddler to simulate modem speeds and all of sudden I can replicate the WSOD on my local PC. So it appears to be a slow or temporarily slow connection when opening a popup window that causes it to choke, at least in my test environment.

I did another test running IE without add-ons, iexplore.exe -extoff, but end up with the same result. I also fixed an issue where the iframe on the page was being recreated everytime the URL for the iframe changed. Part of my logic was omitted. Now the iframe is only created once. After that only the src attribute is updated when I want to load new content... my goof. I noticed some lingering window references in JavaScript closures, so now those are explicitly set to null in the closures when I'm done with them.

I've also done some memory leak investigation: - As far as I can tell I do not have any circular references in the DOM and JavaScript or the other leak patterns mentioned here, http://www.ibm.com/developerworks/web/library/wa-memleak/?S_TACT=105AGX52&amp;S_CMP=cn-a-wa

  • I've added the Crockenator's purge code for IE memory leaks (see 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 &lt; 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 &lt; l; i += 1) {
            purge(d.childNodes[i]);
        }
    }        
    
    } $(window).unload(function() { purge(document.body); //alert("purge count: " + purgeCount); });

    });

None of my improvements have fixed the problem. in my local test scenario. Any ideas? Anyone? Anyone? Bueller?

Last Update

Thanks David for pointing out that it was session state causing the problems in the web services. "ASP.NET queues all requests to the same 'session'. So if the first request blocks for too long, it will hold up any other queued requests."

So what we ended up doing was try to minimize web services using session state but we also added the recommended settings by Microsoft for the number of connections, see http://msdn.microsoft.com/en-us/library/ff647786.aspx#scalenetchapt10_topic9

A: 

I think you may be having an issue with Session request synchronization. Have you marked your web service handlers as requiring session state?

ASP.NET queues all requests to the same "session". So if the first request blocks for too long, it will hold up any other queued requests. You can turn off session state for the page to avoid this and be truly asynchronous, however you will be unable to access session on the server, etc.

If you are using .ashx, you have to use an interface to get access to session state,the default is off, so check if you added one of these interfaces and remove if possible:

public class FooHandler : IHttpHandler, IReadOnlySessionState // readonly access

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

If you are using an aspx page, it is on by default and you have to turn it off with a Page directive attribute:

    <%@ Page language="c#" Codebehind="WebForm1.aspx.cs"
AutoEventWireup="false" Inherits="WebApplication1.WebForm1"
EnableSessionState="false" %>
David
@david - The web service methods that are causing the issue do use session state, i.e. [WebMethod(EnableSession = true)]. Is there a better way do access session in a service than via [WebMethod(EnableSession = true)]? The web services I run need to be aware of a user's session and be called from JavaScript.
nickyt
Unfortunately ASP.NET enforces request synchronization for sessions, you would have to implement some other form of cross-request state storage and make your webmethods disable session state. The request synchronization for session state is why you dont have to "lock" to get/set from the session. If you move your storage to a user specific hash in Application[], you wont get request synchronization, but you will need to Application.Lock() and Application.Unlock() when accessing that data.
David
Do you need write access to session state? if you change them to readonly, they wont block each other, however they will still be blocked by any other page that gets a write lock on the session. See the last section of: http://msdn.microsoft.com/en-us/library/ms178581.aspx
David