Welcome to Tech-Review.Org Sign in | Join | Help

.net_2.0

My coding blog entries. Typically will either be more complex coding examples or overcoming product issues / troubleshooting resolutions.
Lets Talk ScriptManager

Introduction: 

 

One of the most confusing aspects of Ajax is not the UpdatePanel, UpdateProgress or AjaxToolKit controls.  In fact all of those 'features' provide almost a no programming required - drag and drop functionality, from the Visual Studio IDE which makes Visual Studio the tool to use when prograaming any .Net language.  No, the most confusing part of the whole Ajax experience is the ScriptManager control.  When to use it is not the real hardship but it is how to use it when you need to use custom javascript to provide enhanced client-side functionality (and thusly prevent unwarranted postbacks of any flavor to the server).

 

Before Ajax, all of our client side scripts were registered through Page level methods. such as:

Page.ClientScript.GetPostBackEventReference(this, String.Empty);

 

However, anyone that has limited exposure to Scripting and merely has used a copy and paste method to make things will definately struggle making what worked before using Ajax - work with Ajax.  So, in this entry - what I will attempt to do is clarify some of the misconceptions and concepts lacking from the Ajax documentation site.

 

When to include a ScriptManager:

You must include a ScriptManager if you are using any controls from the System,Web.Extensions (Core Ajax Extensions), System.Web.Extensions.Design (Ajax Futures), or any control from the AjaxControlsToolkit.  All of which use javascript at some level to provide the asynchronous communications via script and thus the 'Ajax enabled' controls. The ScriptManger is responsible for handling the core features of the all the Ajax Extensions and most importantly:

  • Determining if the client's browser can handle javascript and java objects, and overall the underlying communications structure required.
  • Determining what chunks get sent back to the client after a request is made based upon if the request was a asynchronous partial update request, a webservice method request or page method request.
  • Handling of errors during asynchronous requests (which often occur after any actual .Net coding errors).
  • Loading, disposing and otherwise co-ordinating how and when actual scripts that fall outside of those of the extenders of the three core pieces of the Ajax Framework are delivered to the client.

Little known fact - The ScriptManger derives alot of its own functionality by extending the .Net's Page class by extending it. However, not all Page level methods have directly correlatable equivelants due to the nature of the extension and hence lies some of the misconceptions and issues that arise when working with the ScriptManager directly - when dealing with custom scripting. After all, a Extension is programming logic that extends a class or method (all of which are the core of what makes a control) usually by adding functionality to or limiting existing functionality by overriding protected methods (or any other words altering expected behavior).

 

How to Include / Reference the ScriptManager in ASPX / ASCX pages / controls:

I am going to assume that you have already followed the installation or upgrade (from previous beta versions of Microsoft's Ajax) ; thus, I shall not go over the entries for the web.config. 

 

MasterPage programming folks:

 You actually will have more difficulty with the ScriptManager than those using custom IHTTP handlers to render content.  The biggest reason why is the ability to embed multiple Content PlaceHolders which can reference seperate .aspx pages. While it is a handy feature to be able to do so - it offers some programming complexity that otherwise would not be need to be considered.

Just a MasterPage.

If all you have is a MasterPage and does not have ContentPlaceHolders - you may embed the ScriptManager as such:

</head>
<body>
    <form id="form1" runat="server">
        <div>
            <asp:ScriptManager ID="ScriptManager1"
                               runat="server" />

Note that this is placed after the FORM tag.

 

MasterPage with a Single ContentPlaceholder

IF and ONLY IF - you are using a single ContentPlaceHolder on the MasterPage, and the MasterPage itself does not contain a ScriptManager control.

Inside the .aspx page that will be loaded by the ContentPlaceHolder:

<asp:Content ContentPlaceHolderID="SampleContent" Runat="Server">
    <asp:ScriptManager runat="server" />

MasterPage with a Scriptmanger on it and ContentPlaceholder(s)

A Web page can contain only one ScriptManager control. Period.

It is irregardless if a ScriptManager is either directly on the page itself or indirectly inside a nested or parent component and this includes ContentPlaceHolders. The ScriptManagerProxy control enables you to add scripts and services to content pages and to user controls, where the master page or host page already contains a ScriptManager control. While in some cases it will appear you can get away with it - expect either errors or interesting unexpected behavior. 

On the MasterPage you would add:

</head>
<body>
    <form id="form1" runat="server">
        <div>
            <asp:ScriptManager ID="ScriptManager1"
                               runat="server" />

On any of the web controls, user controls or other ContentPlaceHolders then you embed this in their corresponding .aspx or ascx pages:

<asp:ScriptManagerProxy ID="scriptManagerProxy1" runat="Server" />

If you are using a custom IHHTP handler - I recommend adding the ScriptManger to the page that you use to generate the core content.  IE you use a default.ascx to provide the overall skinned look, then this would be the page you embed the ScriptManger - just make sure you are properly generating a <head> and <form> and place the ScriptManger after the <form> tag.

In this example the the admin.ascx is the actual page that holds all of the content. The parent page (.aspx) loads this ascx dynamically.

 <%@ Control Language="C#" %>
 <ajax:ScriptManager ID="SM"  EnablePartialRendering="true"  ScriptMode="Release" runat="server"  />
<asp:PlaceHolder id="Content"  Runat="Server"/>

 

Exception: IFRAME IMPLEMENTATIONS

If you are using IFRAMES - and require Ajax functionality in both the frame and the parent - this is the only time where the parent page or master page may have seperate ScriptManagers.  This is because the Iframe actually loads a seperate DOM instance for the IFRAME page that is loaded.  I personally use this technique for my admin UI where the only function I want on my parent page is a menu and a toolbar that uses the hover menu and the collapsible panel, but the target frame is used for displaying actual pages that render gridviews or other forms. However, note - features like the ModalPopUp Extender WILL not grey out the parent page just the IFRAME content it is invoked from. However, the Iframe may not contain multiple ScriptManagers nor may the Parent Page less that of those in Iframes.

Referencing ScriptManager from Code-Behind

Personally - one of the most overlooked aspect of Ajax in general is the ability to handle most all of the Ajax features and controls from code-behind instead of from the UI design.  The ScriptManager can be referenced anywhere and anytime during the Page Life cycle making it extrememly easy to bypass the need for registering ScriptManagerProxies...

Here is how you go about it:

namespace MyNameSpace
{
using....{whatever you need]

//include for ajax and toolkit

using System.Web.Script;
using AjaxControlToolkit;
using System.Web.UI;
using System.Web.UI.Design;

public partial class MyCass : CommonPage

{

//Declare the ScriptManger so we can reference throughout the class

ScriptManager SM;

protected void Page_OnInit(object sender, Eventargs e)

{

 SM = ScriptManager.GetCurrent(Page);

}

Now, anywhere in the class you reference SM directly instead of System.Web.UI.ScriptManger.  This insures that regardless how many controls, pages, etc you have - you can embed the <asp:ScriptManager /> tag at the root page (such as a MasterPage itself) and furthermore - it is registering properly.  The issue with writing via the System.Web.UI.ScriptManager is that you can possibly have threading issues or lost data due to there not being an actual instance declared.  Besides that - it is poor programming practice and prevents you from adding error trapping for asynchornous requests and the likes in the controls / pages that require ScriptManager functionality / features.

If you use the code-behind method there will never really be a requirement to use the ScriptManagerProxy class.  Not saying there is not a use for the ScriptManagerProxy class - however it is one additional level of abstraction - when or if used.  No need to call a proxy if you can get the core ScriptManager directly in my opinion.

Note on Iframes: The SM=ScriptManager.GetCurrent(Page) will not cross boundaries.  If you have an Iframe and do not have a scriptmanger in the page loaded in the iframe - the SM will be null.  Vice versa if your Iframe has a ScriptManger but the parent doesn't have one - the parent if it uses this GetCurrent(Page) will return null even though the iframe has a ScriptManager found.

 

 In my next installment I'll go over the finer details of when and how to register scripts with the ScriptManager and implementing some additional tricks to leverage the asynchronous benefits of Ajax.

Posted: Thursday, February 08, 2007 12:59 AM by Jody
Filed under:

Comments

Mike said:

Here's the thing... I'm trying to Ajax enable an existing project.  I've made all the necessary updates to the web.config file and am able to use the Ajax objects within my pages.  I'm not, however, able to use ScriptManager or any other Ajax object within my class assemblies.  When I attempt to reference System.Web.UI.Design or System.Web.UI.Script, they are not recognized by the compiler.  Is there anything else I need to do to configure the assemblies to recognize the Ajax libraries?

# February 25, 2007 2:20 PM

Jody said:

When referencing - are you selecting Add Reference -> then from the .Net tab scroll down and the select the Syste.Web, System.Web.Extensions and System.Extensions.Design...to your project. If using the APP_CODE directory for placing in your code that too will need referencing (as well as the using statement.

It may be perhaps you are trying to reference the actual dll?  

What actual error are you recieving from the actual compiler?

# February 25, 2007 6:04 PM

Boy from Oz said:

Hi Jody

Problem resolved.  I found another of your postings on this site which warns against setting the frameborder of the iframe to a "yes" or "no" and suggests instead to use a numeric value...so I did, and now it all works perfectly!  Thanks so much, I was worried this would have me stumped for days, but was fortunate enough to come across your other postings.

Keep up the great work!  Thanks again!

cheers from sunny Oz!

# September 17, 2007 2:44 PM

Abby said:

Hi Jody,

I'm trying to integrate web parts in SharePoint site that use the AJAX timer control. To do this, i need to add a asp:scriptmanager onto the master page of my site....

But the SharePoint Designer gives me the following error when i add : "<asp:ScriptManager runat="server" ID="ScriptManager1"></asp:ScriptManager>" i get the following error :

In Internet Explorer, the tag <asp:ScriptManager> is not permitted.

URGENT HELP REQUIRED....

Thanks and regards !!

# October 20, 2007 6:50 AM

Prashant said:

I am not able to use scriptmanager on master page as well as .aspx pages those are related to master page.

I have been added refrence of Ajax.dll too. Please help.

Thanks

# December 21, 2007 6:26 AM
New Comments to this post are disabled