Demystifying ‘Sys is undefined’

 

Are you running into this error on your ASP.NET AJAX enabled web site? Does it only happen on some machines or on some browsers? Here’s how you can get to the bottom of it.

Here's a little background on what is happening…

When you have a ScriptManager on a page, ASP.NET AJAX will render a few script tags to load the various ASP.NET AJAX Scripts, and some inline script to get everything initialized and running. If you view source on the page as rendered by your browser, you should see something like this:

<script type="text/javascript">
Sys.WebForms.PageRequestManager._initialize('ScriptManager1', document.getElementById('form1'));
Sys.WebForms.PageRequestManager.getInstance()._updateControls([], [], [], 90);
</script>

When the browser goes to run that code, it’s going to expect Sys.WebForms.PageRequestManager to be defined somewhere. That somewhere happens to be in the other scripts that are loaded from script tags that look like this:

<script src="/MyWebApp/ScriptResource.axd?[snip - long query string]" type="text/javascript"></script>

If the browser fails to load those scripts, the script engine can’t find the definition for Sys, Sys.WebForms, Sys.WebFormsPageRequestManager, and thus the error.

So why would those scripts fail to load? We’ve seen several reasons:

1. The browser fails to load the compressed script

This is usually the case if you get the error on IE6, but not on other browsers.

The Script Resource Handler – ScriptResource.axd compresses the scripts before returning them to the browser. In pre-RTM releases, the handler did it all the time for all browsers, and it wasn’t configurable. There is an issue in one of the components of IE6 that prevents it from loading compressed scripts correctly. See KB article here. In RTM builds, we’ve made two fixes for this. One, we don’t compress if IE6 is the browser client. Two, we’ve now made compression configurable. Here’s how you can toggle the web.config.

How do you fix it? First, make sure you are using the AJAX Extensions 1.0 RTM release. That alone should be enough. You can also try turning off compression by editing your web.config to have the following:

<system.web.extensions>
<scripting>
<scriptResourceHandler enableCompression="false" enableCaching="true" />
</scripting>
</system.web.extensions>

2. The required configuration for ScriptResourceHandler doesn’t exist for the web.config for your application

Make sure your web.config contains the entries from the default web.config file provided with the extensions install. (default location: C:\Program Files\Microsoft ASP.NET\ASP.NET 2.0 AJAX Extensions\v1.0.61025)

3. The virtual directory you are using for your web, isn’t correctly marked as an application (thus the configuration isn’t getting loaded) - This would happen for IIS webs.

Make sure that you are using a Web Application, and not just a Virtual Directory 

4. ScriptResource.axd requests return 404

This usually points to a mis-configuration of ASP.NET as a whole. On a default installation of ASP.NET, any web request to a resource ending in .axd is passed from IIS to ASP.NET via an isapi mapping. Additionally the mapping is configured to not check if the file exists. If that mapping does not exist, or the check if file exists isn't disabled, then IIS will attempt to find the physical file ScriptResource.axd, won't find it, and return 404.

You can check to see if this is the problem by coipy/pasting the full url to ScriptResource.axd from here, and seeing what it returns

<script src="/MyWebApp/ScriptResource.axd?[snip - long query string]" type="text/javascript"></script>

How do you fix this? If ASP.NET isn't properly installed at all, you can run the "aspnet_regiis.exe" command line tool to fix it up. It's located in C:\WINDOWS\Microsoft.Net\Framework\v2.0.50727. You can run "aspnet_regiis -i -enable", which does the full registration of ASP.NET with IIS and makes sure the ISAPI is enabled in IIS6. You can also run "aspnet_regiis -s w3svc/1/root/MyWebApp" to only fix up the registration for your web application.

2 Comments

  • Just because you reference a .js file that contains a function, you can never be assured the library actually loaded. This happens more times than you might think.
    Think about it:You see the same thing with broken images on web pages - you simply hit refresh and viola! They are there.

    I think its good practice in javascript to always check your external resources before you try using them, this way the user doesn't have to see any nasty javascript errors.

    I like to spit something out into the head of my page before any links and then force all js files to use it.

    example:
    function hasloaded()
    {
    if(typeOf(Sys) == 'undefined'){
    alert('Please try again. The page hasn't finished loading. If you feel you have gotten this message in error, try refreshing the page.');
    return false;
    }
    else
    {
    return true;
    }
    }

    if(hasLoaded()){
    //do whatever I want with Sys.
    }

    This is much better than getting trouble tickets for someone saying that 'Sys' is undefined.

    I'm not sure MS put something like this in the new AJAX framework or not. Would like to know if they did.

  • Great tip, thanks!

    The AJAX Extensions scripts will be loaded before our inline script executes because of the order in which things are rendered. So the atlas scripts only being partially loaded (or not loaded at all), wouldn't contribute to this problem.

    If you use the ASP.NET AJAX ScriptManager control to add other scripts to your page, you are protected from the similar issue as well. The ScriptManager will make sure your scripts are rendered before your UI, which forces the browser to load them before rendering your UI.

    Note that there is a property on ScriptManager that controls this behavior (LoadScriptsBeforeUI), so if you set that to false, you will want to employ some defensive programming like your sample above.

Comments have been disabled for this content.