See Joel Program

October 3, 2008

Fixing Sys.Application.initialize … Again

Filed under: ASP.NET AJAX — Joel Rumerman @ 1:11 pm

Download the text version of the changes

In a past post, I highlighted a problem with the method ASP.NET AJAX uses to determine if the DOM is ready to be modified. (Other developers have since commented that they’ve seen this problem in the wild.) I followed that post with another one where I provided code changes to fix the problem. Through comments on that post, talking with other developers, and reading other people’s blogs, I determined that it was a little bit unelegant and didn’t take into account all situations.

So, I wanted to take a few minutes and revisit this topic; hopefully for the last time, and provide a more complete ASP.NET AJAX solution for this problem.

The code I’m about to cover wasn’t designed, developed, or thought up by me. Rather it’s a mis-mash of different developers working on a problem. You could say it’s open source at its best. The code I’m actually going to provide comes from Diego Perini. He has put together a complete solution that works across all browsers. He, in turn, borrows from Dean Edwards and others.

So, I’ve adapted his code to the ASP.NET AJAX environment.

First, here’s the new version of Sys.Application.initialize:

  function Sys$_Application$initialize() {
      if(!this._initialized && !this._initializing) {
          this._initializing = true;
          var u = window.navigator.userAgent.toLowerCase(),
              v = parseFloat(u.match(/.+(?:rv|it|ml|ra|ie)[\/: ]([\d.]+)/)[1]);

          var initializeDelegate = Function.createDelegate(this, this._doInitialize);
          
          if (/WebKit/i.test(u) && v < 525.13) 
          { 
              this._load_timer = window.setInterval(function() 
              {
                  if (/loaded|complete/.test(document.readyState))
                  {
                      initializeDelegate(); 
                  }
              }, 10);
          }
          else if (/msie/.test(u) && !window.opera)
          {
              document.attachEvent('onreadystatechange',
                  function (e) {
                      if (document.readyState == 'complete') {
                          document.detachEvent('on'+e.type, arguments.callee);
                          initializeDelegate();
                      }
                  }
              );
              if (window == top) {
                  (function () {
                      try {
                          document.documentElement.doScroll('left');
                      } catch (e) {
                          setTimeout(arguments.callee, 10);
                          return;
                      }
                      initializeDelegate();
                  })();
              }

          }
          else if (document.addEventListener
              &&  ((/opera\//.test(u) && v > 9) ||
                  (/gecko\//.test(u) && v >= 1.8) ||
                  (/khtml\//.test(u) && v >= 4.0) ||
                  (/webkit\//.test(u) && v >= 525.13))) {
              document.addEventListener("DOMContentLoaded", initializeDelegate, false);
          }
          else
          {
              $addHandler(window, "load", initializeDelegate);
          }   
      }
  }

Here’s the _doInitialize method:

  function Sys$_Application$_doInitialize() {
       if (this._initialized) {
           return;
       }
       Sys._Application.callBaseMethod(this, 'initialize');
       if (this._load_timer !== null)
       {
           clearInterval(this._load_timer);
           this._load_timer = null;
       }
       var handler = this.get_events().getHandler("init");
       if (handler) {
           this.beginCreateComponents();
           handler(this, Sys.EventArgs.Empty);
           this.endCreateComponents();
       }
       if (Sys.WebForms) {
           this._beginRequestHandler = Function.createDelegate(this, this._onPageRequestManagerBeginRequest);
           Sys.WebForms.PageRequestManager.getInstance().add_beginRequest(this._beginRequestHandler);
           this._endRequestHandler = Function.createDelegate(this, this._onPageRequestManagerEndRequest);
           Sys.WebForms.PageRequestManager.getInstance().add_endRequest(this._endRequestHandler);
       }
       
       var loadedEntry = this.get_stateString();
       if (loadedEntry !== this._currentEntry) {
           this._navigate(loadedEntry);
       }

       this.raiseLoad();
       this._initializing = false;
   }

Finally, here’s the Sys.Application._loadHandler method, which hasn’t changed since the first version.

function Sys$_Application$_loadHandler() {
    if(this._loadHandlerDelegate) {
        Sys.UI.DomEvent.removeHandler(window, "load", this._loadHandlerDelegate);
        this._loadHandlerDelegate = null;
    }
    this._initializing = true;
    this._doInitialize();
}

Just like last time, the majority of the work takes place in the initalize method.

15 Comments »

  1. Joel,
    your code will now cover iframes and framesets through the reliable “onreadystatechange” event.

    If the targeted window is the main window, not a subwindow, it will be handled by the doScroll(“left”) trick.

    Nice job man, hope it will solve most initializations problems for ASP.net

    Have the best,

    Diego

    Comment by Diego Perini — October 10, 2008 @ 10:40 am

  2. Joel,

    Thanks for putting so much time into this complex issue. I have spent two solid days/nights wrestling with sporadic Operation Aborted errors using Microsoft’s Virtual Earth control thinking it must be a problem in my code rather than an Ajax issue.

    As this issue affects only one page on my site (at least for now) I chose to follow Nikhil Shampir’s suggestion (http://blogs.esri.com/Dev/blogs/arcgisserver/archive/2008/09/08/Operation-aborted-error-in-Internet-Explorer.aspx) of simply redefining Sys.Application.initialize, Sys.Application._doInitialize and Sys.Application._loadHandler within the user control that contains the VE map rather than messing with MicrosoftAjax.js.

    This works a treat so thanks again to you and Nikhil for providing such clear and complete suggestions for solving the problem.

    -Chuck

    Comment by Chuck Richardson — October 16, 2008 @ 1:22 pm

  3. […] Fixing Sys.Application.initialize … Again […]

    Pingback by Sys.Application initialization steps « Update Panel .NET — October 17, 2008 @ 3:30 pm

  4. Hi Joel,

    I am running into exactly the problem you describe in a critical application and I am in the midst of incorporting the fix you provided in our app. But I noticed in my version of MicrosoftAjax.js file, this piece of code in the _doInitialize() is missing:

    if (Sys.WebForms) {
    this._beginRequestHandler = Function.createDelegate(this, this._onPageRequestManagerBeginRequest);
    Sys.WebForms.PageRequestManager.getInstance().add_beginRequest(this._beginRequestHandler);
    this._endRequestHandler = Function.createDelegate(this, this._onPageRequestManagerEndRequest);
    Sys.WebForms.PageRequestManager.getInstance().add_endRequest(this._endRequestHandler);
    }

    var loadedEntry = this.get_stateString();
    if (loadedEntry !== this._currentEntry) {
    this._navigate(loadedEntry);
    }

    It is giving me an undefined error on this._onPageRequestManagerBeginRequest. Can I leave the code out?

    Thanks for posting this fix and I hope it will fix our problem.

    Matthew

    Comment by Matthew — November 14, 2008 @ 7:09 am

  5. Hi Matthew,

    (Sorry it took a while to approve your comment and post back. I’ve been out of town.)

    I’m not real sure why it’s giving you an undefined error message for the _onPageRequestManagerBeginRequest method. It sounds like there might be a syntax error in the code that is preventing it from reading the rest of the file and parsing the methods.

    It should parse all the methods before it enters the _doInitialize method so I’m not sure how it wouldn’t see the _onPageRequestManagerBeginRequest method and still get into the _doInitialize method.

    Question: are you running 3.5 or 2.0? This was written for 3.5, but it should work with some slight modifications for 2.0.

    So to answer your question, no, you cannot leave out that code if you want the history functionality to work correctly.

    Let me know if I can help some more.

    Comment by Joel Rumerman — November 20, 2008 @ 5:15 pm

  6. Hi Joel,

    I am using .NET framework 2.0. The MicrosoftAjax.js that comes with AJAX extension 1.0 does not have the
    _onPageRequestManagerBeginRequest method defined. However I incorporated your fix and tested it out with your test page, it runs fine. Would you be able to show me what needs to be modified for .NET 2.0? I thought this is a javascript fix, so it shouldn’t be dependent on the .NET framework.

    Thanks for your help.

    Comment by Matthew — November 24, 2008 @ 12:51 pm

  7. Hi Matthew,

    I guess when I asked if you were running 2.0 or 3.5 I really meant were you running ASP.NET AJAX 1.0 or ASP.NET AJAX 3.5. You’re right, the version of the .NET Framework doesn’t matter. What matters is what version of Microsoft Ajax you’re using, which is tied to your version of ASP.NET AJAX.

    Ok … based upon what I see in the 1.0 version and what I see in the 3.5 version, the change you need to do is remove the

    if (Sys.WebForms) if-then block from the _doInitialize method.

    Also, remove the code right below that which checks for loadedEntry and then calls navigate.

    Those two code blocks are the only new parts of the Microsoft Ajax 3.5 that relate to this fix.

    I thinks that it. Let me know if that doesn’t work.

    Comment by Joel Rumerman — November 24, 2008 @ 1:25 pm

  8. Hi Joel,

    Cool, I did remove the two code blocks and it is working fine.

    Thanks for your help again.

    Comment by Matthew — November 25, 2008 @ 12:16 pm

  9. Hi Joel,

    Can you point me to a source that describes how to go about getting this update in place in the AJAX source code.

    Greatly Appreciated

    Comment by Dylan Jones — December 4, 2008 @ 4:03 pm

  10. Hi Dylan,

    Here’s a link that describes how to replace the default Ajax JS files with custom ones.

    Comment by Joel Rumerman — December 4, 2008 @ 4:26 pm

  11. Joel,

    Thanks for all your help to date. I completed the updates back on December 4th adn we have been succesfully running in production until last Saturday Jan 3rd. We can not locate any code change that took place that would have impacted this. However, we did publish the site again to address a minor, and unrelated, issue. Now we are seeing this error again on the same clients we saw it on earlier. Those with slower connections. Would you have any idea what could have happened? We have trying to track this down since Saturday morning with no success.

    Greatly Appreciated

    Comment by Dylan — January 4, 2009 @ 5:16 pm

    • Hi Dylan,

      If you had it fixed and then you did a release, 99% its somewhere in the release :).

      Any upgrades to the ASP.NET AJAX Framework (i.e. switch from 1.0 to 3.5)? The only thing I can think of is to use Fiddler to guarantee that the modified MicrosoftAjax.js file is coming down as expected. If it is, and clients are getting operation aborted errors, then I’m at a loss. Maybe your other minor fix causes an Operation Aborted error on its own??

      Good luck. Contact me again if you I can be of more help. Feel free to email me directly. JRumerman at yahoo.com

      Comment by Joel Rumerman — January 4, 2009 @ 8:37 pm

  12. Hi Joel,

    Where should I be putting above script. I am new ajax.

    Thanks
    Ajay

    Comment by Ajay — July 22, 2009 @ 6:07 am

  13. […] number of ASP.Net AJAX enabled server controls on the web page. The issue is explained here, https://seejoelprogram.wordpress.com/2008/10/03/fixing-sysapplicationinitialize-again . I added this fix to my project and all is good now. This fix from what I can tell is still […]

    Pingback by Learn Dash Ajax Dot Com | Internet Explorer's Infamous Operation Aborted Error — December 15, 2010 @ 11:46 am

  14. […] number of ASP.Net AJAX enabled server controls on the web page. The issue is explained here, https://seejoelprogram.wordpress.com/2008/10/03/fixing-sysapplicationinitialize-again . I added this fix to my project and all is good now. This fix from what I can tell is still […]

    Pingback by Internet Explorer’s Infamous Operation Aborted Error | Nick and the Internet Dot Com — March 16, 2012 @ 6:04 pm


RSS feed for comments on this post. TrackBack URI

Leave a comment

Blog at WordPress.com.