Updated your web.config, but Sys is still undefined?
AJAX, ASP.NET, JavaScript By Dave Ward on August 16th, 2007
If you Google the error you’ll find a lot of results about updating your web.config to enable ASP.NET AJAX (which is a necessary step), but what if you’ve already done that? Not only will your search be an exercise in frustration, but it will lead you down the wrong path completely. Maybe I can help.
After web.config problems, the most common reason for this error is JavaScript that references the Sys namespace too early. Take this code, for example:
<head> <script type="text/javascript"> Sys.WebForms.PageRequestManager.getInstance().add_endRequest(End); function End(sender, args) { } </script> </head> <body> <form id="form1" runat="server"> <asp:ScriptManager ID="sm1" runat="server" /> <asp:UpdatePanel ID="up1" runat="server"> <ContentTemplate> <!-- Interesting content goes here --> </ContentTemplate> </asp:UpdatePanel> </form> </body>
Loading this page will result in a Sys undefined error, identical to the one in the screenshot above. The reason for it is simple: The Sys namespace really is undefined when the script block executes.
The ScriptManager control injects JavaScript includes to initialize the ASP.NET AJAX Framework, the ScriptManager, and then the UpdatePanel, but it injects the bulk of that JavaScript in the exact location that the ScriptManager control is positioned at in the page. So, the script block in the page head tries to access the PageRequestManager long before the AJAX Framework has been fully loaded. Hence the error.
The same thing happens if you try to include the same JavaScript code from an external file in the head, or even in the ScriptManager’s Scripts collection.
The Quick Fix
The most obvious fix for this is to move the script block below the ScriptManager control:
<asp:ScriptManager ID="sm1" runat="server" /> <script type="text/javascript"> Sys.WebForms.PageRequestManager.getInstance().add_endRequest(End); function End(sender, args) { } </script> <asp:UpdatePanel ID="up1" runat="server"> <ContentTemplate> <!-- Interesting content goes here --> </ContentTemplate> </asp:UpdatePanel>
That’s the same JavaScript code, but now it works because it’s referencing the PageRequestManager after the AJAX Framework has been initialized. While it does work, hopefully this solution doesn’t sit well with you. It’s not a very good one.
A Better Way
The correct way to remedy this problem is to add the script to the ScriptManager’s Scripts collection and then call our wireups in a Sys.Application.init event handler:
<asp:ScriptManager ID="sm1" runat="server"> <Scripts> <asp:ScriptReference Path="Init.js" /> </Scripts> </asp:ScriptManager> <asp:UpdatePanel ID="up1" runat="server"> <ContentTemplate> <!-- Interesting content goes here --> </ContentTemplate> </asp:UpdatePanel>
Init.js:
Sys.Application.add_init(AppInit); function AppInit(sender) { Sys.WebForms.PageRequestManager.getInstance().add_endRequest(End); } function End(sender, args) { }
This is much better. Not only is it a bit more sturdy, but it’s just good practice to separate presentation from functionality as much as possible.
Remember, all of your JavaScript functions are globally scoped. So, the AppInit function could still call functions defined at the page level or in other script includes. This is especially handy if you want to use Control.ClientID to more robustly reference controls in your client script, since you can’t do that inside a JavaScript include file.
Similar posts
What do you think? Your comments are welcomed.
I appreciate all of your comments, questions, and other feedback, but please try to stay on topic. If you have a question unrelated to this post, I recommend posting on the ASP.NET forums. If you post there and then contact me with a link to the post, I'll try to take a look at it for you.
If you're replying to an existing comment, please use the threading feature. To do this, click the "Reply to this comment" link underneath the comment you're replying to.

Comments
hi,
why is it that the script manager was removed from being added inside the head tag(atlas days)? we might not be able to have that issue?
great blog
It’s output was probably moved to improve the perceived page load performance. Because scripts in the head block the browser from rendering until after they’ve run, delaying them a bit makes the page load feel quicker and more responsive.
goood 5 star from me
Good on you. Nice article - thanks for the heads up and the use of the Scripts collection - otherwise I would have probably done the ‘quick & dirty’ way.
cheers,
Dan
Great article, thanks.
I really love Dave’s articles cause they help me to solve many basic problems of Ajax and they are excellent tips and tricks. It is hard to find solutions somewhere else.
johnaspnet
Thanks pal,
That made a lot of sense and its working for me !!! great ….
Hi
My code works fine in my local machine but i get
“Sys is undefined” error on testing server.
Can you please help me how to solve this problem
regards
gprashantraj
The testing server probably doesn’t have the AJAX Extensions installed on it. The need to be installed on the server, not just on your development machine.
hi
Thanks for your reply
AJAX Entension is already installed on the server.
I get this error when i press enter key in password textbox. I have placed the code in separate JS file and added ScriptReference to Script Manager and implemented the above concept as it is.
Post the ASPX and C#/VB code for that page on the asp.net forums, and email me a link. I’ll try to take a look at it for you.