Don't Use BODY ONLOAD in ASP.NET AJAX Websites

Saturday, December 13, 2008 by ASP.NET AJAX Team | Comments 7

In the past developers used <body onload="..."> to execute some script as soon as the page is loaded. Nowadays this is rather old-fashioned, no matter how you look at it. What's more, it doesn't work as expected in ASP.NET AJAX websites. Consider the following example:

 

<body onload="MyFunction()"
 
<script type="text/javascript"
 
   function MyFunction() 
   { 
      var myAjaxControl = $find("myAjaxControlClientID"); 
      myAjaxControl.doSomething(); 
   } 
 
</script> 
 
</body> 

 

The client-side page load event is fired by the browser as soon as all HTML and scripts have been loaded. However, this happens before the controls' client-side instances have been created. As a result, myAjaxControl will be null and the doSomething() method will trigger a Javascript error. So, a lot better approach is:

 

<body>  
  
<script type="text/javascript"
 
   Sys.Application.add_load(MyFunction); 
  
   function MyFunction()  
   {  
      var myAjaxControl = $find("myAjaxControlClientID");  
      myAjaxControl.doSomething();  
   }  
  
</script> 
  
</body> 

 

In this case MyFunction() will be executed after all client-side control instances have been created and the script will work as expected. Another benefit of using the second approach is that multiple event handlers can be added to the client page load event, whereas only one handler is added if <body onload="..."> is used.

On a side note, you might also want to try a Telerik productivity tool - JustCode. It’s a Visual Studio add-in that offers advanced JavaScript code navigation, refactorings, quick fixes and code analysis features which  can help you be more productive writing JavaScript code. What’s more JustCode can be used for multi-language solutions, as it also provides features for C#, VB.NET, ASP.NET, XAML and HTML.

7 Comments

  • lini 13 Dec
    You can also create a function that uses the reserved name "pageLoad" and it will be automatically executed by ASP.NET AJAX during the load application event:

       function pageLoad()  
       {  
          var myAjaxControl = $find("myAjaxControlClientID");  
          myAjaxControl.doSomething();  
       } 

    You can also use the "pageUnload" to execute code when the browser leaves the page.
  • violentk 14 Dec
    Thanks for the tip, i noticed Sys.Application.add_load(MyFunction)  code must be placed after scriptmanager. Else, 'Sys' will not be detected. I suppose putting it in JS file may cause Sys = NULL error as JS file is loaded slower than scriptmanager. But its still better than body.onload = function(e) {}

     

  • hart 15 Dec
    Thanks for the post, very helpful.

    However, I found out that the load event is fired after every postback/callback when I want to run some code only once.

    So here is what I found:
    http://stackoverflow.com/questions/40912/how-to-check-if-page-is-postback-within-reserved-function-pageload-on-aspnet-aj
    <script type="text/javascript" > 
    //<![CDATA[ 
    Sys.Application.add_init(AppInit); 
    function AppInit()  
    {   
        Sys.Application.add_load(RunOnce); 
     
    function RunOnce()  
    {  // This will only happen once per GET request to the page.   
        test(); 
        Sys.Application.remove_load(RunOnce); 
     
    function test() 
    alert('test'); //DEBUG 
    //]]> 
    </script> 

  • Matt 17 Dec
    What about testing if a user has JavaScript enabled and displaying a message to them if not? Surely the onload method is appropriate here. For example if we just want to run a small function to hide a div saying "hey turn on JavaScript", we would need to use the body onload otherwise users would see the div or a flicker of it on load.
  • Dimo 19 Dec
    Hi Matt,

    If you want to execute some Javascript as early as possible, then the modern and recommended approach to do this is to attach a handler to the client-side page load event. This is pretty much the same as using <body onload="">, but better. Here is an example:

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> 
    <html xmlns="http://www.w3.org/1999/xhtml"
    <head> 
    <meta http-equiv="content-type" content="text/html; charset=windows-1251" /> 
    <title>Executing Script on Page Load</title> 
    <script type="text/javascript"
    if (window.addEventListener) // DOM  
        window.addEventListener('load', pageLoadProcedures, false)  
    else if (window.attachEvent) // IE  
        window.attachEvent('onload', pageLoadProcedures)  
    else if (document.getElementById)  
        window.onload = pageLoadProcedures;  
     
    function pageLoadProcedures() {  
        document.getElementById("EnableJS").style.display = "none";  
    }  
      
    </script>  
    <style type="text/css">#EnableJS{color:red;font:bold 14px arial,sans-serif}</style>  
    </head> 
    <body>  
    <id="EnableJS">Javascript is disabled. Please enable it!</p>  
    <h1>Javascript Detection</h1>  
    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. In vitae justo a tellus pellentesque adipiscing.</p>  
     </body>  
    </html>  
      

  • Curda 20 Jan
    A solution could be like this:

    instead using the:

    <body onload="shet();"

    use:

    <script type="text/javascript"
    window.onload = function senf(){ 
    document.reg.submit(); 
    </script> 


    well see ya!

  • Richard Thurgood 30 Sep
    Another approach to avoid the mulitple pageLoad() issues would be something like this where you have a flag that determines if the pageLoad() has fired:

    <script type="text/javascript">
    var isLoaded = false;            
    function pageLoad(){
        if (isLoaded == false) {
            isLoaded = true;

            var myAjaxControl = $find("myAjaxControlClientID");  
            myAjaxControl.doSomething();  
        }                
    }
    </script>

Add comment

  1. Formatting options
       
     
     
     
     
       
  2. (optional, emails won't be shown on public pages)
  3. (optional)