65.9K
CodeProject is changing. Read more.
Home

Troubleshooting Partial Rendering Errors in ATLAS and ASP.NET 2.0

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.80/5 (3 votes)

Sep 24, 2006

CPOL

3 min read

viewsIcon

47831

downloadIcon

189

This article helps you resolve some common errors in ASP.NET 2.0 and ATLAS.

Introduction

In my previous article, I explained how to partially render pages in ASP.NET 2.0 and ATLAS with client script. In this article, I will try to help you troubleshoot a series of common errors when you implement the ICallbackEventHandler and IPostBackEventHandler interfaces. To be precise, for each error, I added a sample code to generate the problem and also necessary code that helps you to eliminate the problem.

Using the Code

Error: ‘theForm._EVENTTARGET’ is null or not an object (Applies to: ASP.NET - ATLAS)

This error may appear because of the way you dynamically manipulate your HTML document. If you use non-W3C standard Document Object Model (DOM) methods to dynamically manipulate your document, expect this problem to happen. A good example of this is when you use the non-standard “innerHTML” property of your objects. This may pose a huge compatibility issue with your existing JavaScript code. Hopefully, ASP.NET adds support for non-standard methods and properties, but until then, you need to revise your JavaScript code. I could not find any documentation that shows this behavior by design, therefore, possibly it is a bug.

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Xml;

//@ I encourage you to use this sample code!
//@ This sample is provided under the terms of the GNU General Public License.
//@ for more information visit my blog at TheMorningOutline.com. Cheers!
//@ Shahin
// Implement ICallbackEventHandler
public partial class CallbackSample : System.Web.UI.Page, ICallbackEventHandler
{
    //Callback Counter
    static int i;
    string strMessagetoClient;
    protected void Page_Load(object sender, EventArgs e)
    {
        strMessagetoClient = "";
        if (IsCallback)
        {
            i++;
            // if you make any client side changes here,
            // they are lost and never will be shown
            Label1.Text = "I am lost";
            // Keep track of my Callback time
            strMessagetoClient = String.Format("For the {1} " + 
                                 "time Callback raised at {0}.", 
                                 DateTime.Now.TimeOfDay.ToString(), 
                                 i.ToString());
        }
        // Make sure a Postback doesn't get here
        else if (!IsPostBack)
        {
            // Initilize the Application 
            i = 0;
            // Javascript Plumbing. You only need to
            // this when the page loads for the first time 
            //if you have NO other Postbacks
            ClientScriptPlumbing();
        }
        // Make changes to the calendar. After a postback
        // you can see the calendar changes. 
        // click on the dummy postback button
        // to cause a full postback
        Calendar1.SelectedDate = DateTime.Today.AddDays(i);
        Label1.Text = String.Format("Total number" + 
                      " of Callbacks:{0}", i.ToString());
        ClientScriptPlumbing();
    }
    private void ClientScriptPlumbing()
    {
        // Get a reference of Javasctipt Callback function
        string functionRef = Page.ClientScript.GetCallbackEventReference(this, 
                             "args", "getServerData", 
                             "'this is context from server'");
        // Make a custm function to call it
        string strCallback = "function CallServer(args," + 
                             "context){" + functionRef + ";}";
        Page.ClientScript.RegisterClientScriptBlock(this.GetType(), 
                          "CallServer", strCallback, true);
        //Register other client functions
        Page.ClientScript.RegisterClientScriptBlock(
             this.GetType(), "CommonScripts", @"
                function btnBug_onclick() {
                    CallServer('Hi','Client Call'); 
                    // non-standard 
                    document.body.innerHTML+='<P style=\'color:red;\' > ' + 
                        'From this point, the postback from' + 
                        ' controls doesnt work. Try the Calendar!(to'+
                        'resolve this issue comment this line ' + 
                        'of JS and use the DOM version )<P>';
                    //standard
                    //uncomment the lines below and comment the above line
                    /*
                    newDiv = document.createElement('div');
                    newDiv.id='newDiv';
                    var mytext=document.createTextNode('I was added' + 
                               ' dynamically but unlike innerHTML' + 
                               ' I dont harm your Calendar Postbacks. Use DOM!');
                    newDiv.appendChild(mytext);
                    document.body.appendChild(newDiv);*/
                }
                //Clicking on Button1 makes a Callback 
                //and triggers RaiseCallbackEvent
                function Button1_onclick()
                {
                    CallServer('Hi','Client Call');
                    return false;
                }
                // Receive the string returned by GetCallbackResult
                function getServerData(args, context)
                {
                    myCustomFunc(args);
                }
                // My JS scripts that takes care of partial rendering
                function myCustomFunc(strArgs)
                {
                    var NewTxtArea= document.getElementById('NewTxtArea');
                    if (!NewTxtArea )
                    {
                        var NewTxtArea = document.createElement('textarea');
                        NewTxtArea.id = 'NewTxtArea';
                        NewTxtArea.rows = 10;
                        NewTxtArea.cols = 100;
                        document.body.appendChild(NewTxtArea);
                    }
                    NewTxtArea.value+=strArgs + '\n';
                }
        "
        , true);
    }

    //This is called by CallServer Javascript
    public void RaiseCallbackEvent(string eventArgument)
    {
        // Notice that the any changes you make to webcontrols won't get rendered
        Label1.Text = "This text is never shown!!!";
        strMessagetoClient += "The server side is updated," + 
                              " but I am just a javascript " + 
                              "and too lazy to update your calendar.";
        strMessagetoClient += "To update do a Postback " + 
                              "by clicking on the calendar .";
    }
    //Retrun strMessagetoClient to the clinet. 
    //Notice that it does not refresh your page
    //but it calls the registered javascript getServerData function
    public string GetCallbackResult()
    {
        return strMessagetoClient;
    }
}
<%@ Page Language="C#" AutoEventWireup="true" 
         CodeFile="_EVENTTARGETisNullError .aspx.cs" 
         Inherits="CallbackSample" %>

<!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 id="Head1" runat="server">
    <title>www.themorningoutline.com</title>
</head>
<body id='myBody'>
    <form id="form1" runat="server">
        <asp:Label ID="Label1" runat="server" 
                   Height="8px" Text="Callback" 
                   Width="255px">
        </asp:Label>
        <asp:Calendar ID="Calendar1" 
             runat="server"></asp:Calendar>
        <input id="Button1" language="javascript" 
               onclick="return Button1_onclick()" 
               type="button" value="Callback" />
        <input id="btnBug" type="button" value="Bug me!" 
               language="javascript" 
               onclick="return btnBug_onclick()" /><br />
    </form>
</body>
</html>

Error: ‘_pendingCallbacks[...].async’ is null or not an object (Applies to: ASP.NET – ATLAS)

This error appears when a JavaScript function, which is called by GetCallbackResult, utilizes a variable called ‘i’. This bug was fist discussed back in 2005 in the comment section of a post from Rick Strahl's Web Log called "Script Callbacks in ASP.NET 2.0 interface changes in Visual Studio July CTP" and it exists until today. Apparently, “i” is declared as a global variable in ASP implementation, and by changing it, you are messing with ASP.NET auto-generated scripts. To resolve this problem, declare your variable as a local variable in the function.

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Xml;

//@ I encourage you to use this sample code!
//@ This sample is provided under the terms of the GNU General Public License.
//@ for  more information visit my blog at TheMorningOutline.com. Cheers!
//@ Shahin
// Implement ICallbackEventHandler and IPostBackEventHandler
public partial class PostbackSample : System.Web.UI.Page, 
               ICallbackEventHandler, IPostBackEventHandler
{
    //Callback Counter

    static int i;
    //Postback Counter

    static int j;
    string strMessagetoClient;
    static string CallbackTime;
    protected void Page_Load(object sender, EventArgs e)
    {
        strMessagetoClient = "";
        if (IsCallback)
        {
            i++;
            // Keep track of my Callback time

            CallbackTime = DateTime.Now.TimeOfDay.ToString();
            strMessagetoClient = String.Format("For the {1} time" + 
                                 " Callback raised at {0}.", 
                                 CallbackTime, i.ToString());
            // if you make any clinet side changes here,
            // they are lost and never be shown

            Label1.Text = "I am lost";
        }
        else if (IsPostBack)
        {
            j++;
            // Javascript Plumbing. Normally You would
            // do this in your initial load and
            // RaisePostBackEvent but because Atlas oesn't
            // raise that event you need    
            // to put it here for Atlas partial Postbacks
            ClientScriptPlumbing();
        }
        else
        {
            // Initilize the Application
            i = 0;
            CallbackTime = "Not Yet";
            ClientScriptPlumbing();
        }

        // When a Postback occurs it will take care of Callback UI changes
        // if you want to make UI changes during a Callback and later show them
        // by a postback you must put them in Page_load event here

        Calendar1.SelectedDate = DateTime.Today.AddDays(i);
        Label1.Text = String.Format("Total Callbacks count:{0}" + 
                      " Last Callback Occurred at {1}", 
                      i.ToString(), CallbackTime);

    }

    private void ClientScriptPlumbing()
    {
        // Get a reference of Javasctipt Callback function
        string functionRef = Page.ClientScript.GetCallbackEventReference(this, 
                             "args", "getServerData", 
                             "'this is context from server'");
        // Make a custom function to call it
        string strCallback = "function CallServer(args,context){" + 
                             functionRef + ";}";
        Page.ClientScript.RegisterClientScriptBlock(this.GetType(), 
                                  "CallServer", strCallback, true);
        // Get a reference of Javasctipt Postback function
        functionRef = Page.ClientScript.GetPostBackClientHyperlink(this, 
                                                            "PostBack");
        // Make a custm function to call it
        string strPostBack = "function PostServer(args,context){" + 
                             functionRef + ";}";
        Page.ClientScript.RegisterClientScriptBlock(this.GetType(), 
                                  "PostServer", strPostBack, true);
        //Register other client functions
        Page.ClientScript.RegisterClientScriptBlock(this.GetType(), 
                                                "CommonScripts", @"
    
                var INeedABug=false;
                function btnBugATLAS_onclick() {
                
                 INeedABug=true;
                   newDiv = document.createElement('div');
                   newDiv.id='newDiv';
                   var mytext=document.createTextNode('To resovle this issue' + 
                              ' uncomment the  var i line' + 
                              ' in getServerData function' );
                   newDiv.appendChild(mytext);
                   document.body.appendChild(newDiv);
                 CallServer('bug!','Client Callback');
                
                }

                function Button1_onclick()
                {
                    CallServer('Hi','Client Callback');
                    return false;
                }
                function Button2_onclick()
                {
                    PostServer('Hi','ClientPostback');
                    return false;
                 
                }
                function getServerData(args, context)
                {
                    //uncomment this to resolve the issue
                    // var i
                    myCustomFunc(args);
                    if (INeedABug) i++;
                }
                function myCustomFunc(strArgs)
                {
                    var NewTxtArea= document.getElementById('NewTxtArea');
                    if (!NewTxtArea )
                    {
                        var NewTxtArea = document.createElement('textarea');
                        NewTxtArea.id = 'NewTxtArea';
                        NewTxtArea.rows = 10;
                        NewTxtArea.cols = 100;
                        document.body.appendChild(NewTxtArea);
                    }
                    NewTxtArea.value+=strArgs + '\n';
                }
        "
        , true);
    }

    //This is called by CallServer Javascript

    public void RaiseCallbackEvent(string eventArgument)
    {
        // Notice that any changes you make  here,  won't
        // get rendered

        Label1.Text = "This text is never shown!!!";
        strMessagetoClient += "The server side is updated, " + 
                              "but I am just a javascript " + 
                              "and too lazy to update your " + 
                              "calenadr, ask Postback to do it.";
    }
    //Retrun strMessagetoClient to getServerData. 
    //Notice that this does not refresh your page but it calls
    //the registered javascript getServerData function
    public string GetCallbackResult()
    {
        return strMessagetoClient;
    }

    //This is called by PostServer Javascript and 
    //can be used to force UpdatePanel to refresh
    public void RaisePostBackEvent(string str)
    {
        // Your client side changes here will get rendered
        Calendar2.SelectedDate = DateTime.Today.AddDays(j);
        Label2.Text = String.Format("Total Postback count:{0}" + 
                      " Last Postback Occurred at  {1}", j.ToString(), 
                      DateTime.Now.TimeOfDay.ToString());
    }
}
<%@ Page Language="C#" AutoEventWireup="true" 
         CodeFile="_pendingCallbacksError.aspx.cs" 
         Inherits="PostbackSample" %>

<!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 id="Head1" runat="server">
    <title>www.themorningoutline.com</title>
    
</head>
<body id='myBody'>
    <form id="form1" runat="server">
        <atlas:ScriptManager ID="ScriptManager1" 
               runat="server" EnablePartialRendering="True">
        </atlas:ScriptManager>
        <div>
        </div>
        <atlas:UpdatePanel ID="up1" runat="server">
            <ContentTemplate>
                <asp:Label ID="Label1" runat="server" 
                     Text="Callback" Height="8px" Width="505px"></asp:Label>
                <asp:Calendar ID="Calendar1" runat="server"></asp:Calendar>
                <asp:Label ID="Label2" runat="server" 
                     Text="PostBack" Width="504px"></asp:Label>
                <asp:Calendar ID="Calendar2" runat="server"></asp:Calendar>
                <input id="Button1" language="javascript" 
                     onclick="return Button1_onclick()"
                     type="button" value="Callback" />
                <input id="Button2" language="javascript" 
                       onclick="return Button2_onclick()" 
                       type="button" value="Postback" />
                <input id="Button3" language="javascript" 
                       onclick="return btnBugATLAS_onclick()" 
                       type="button" value="Bug me!" /><br />
            </ContentTemplate>
        </atlas:UpdatePanel>
    </form>
</body>
</html>

Error: JavaScript alert “unknown error” (Applies to: ATLAS)

This error may appear when you are dealing with strings that contain tags in your JavaScript and you place your JavaScript in the head section or a separate file. Also, if you have any other tags that are not properly closed, you may get this error. To resolve this problem, always put your JavaScript code inside <!-- -->, or better use the ClientScript object of ASP.NET to register your JavaScript functions. You are very prone to get this error if you are dealing with XML in your JavaScript code.

<%@ Page Language="C#" %>

<!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 id="Head1" runat="server">
    <title>www.themorningoutline.com</title>

<script type='text/javascript'>
//@ TheMorningOutline.com provided this under the terms of the GNU GPL.

//Put the following function within <!--  --> or move it 

                    to the body to get rid of unknown error

function genXML()
{     
    var  strArgs= '<?xml version=\'1.0\'  standalone=\'yes\'?>'
    strArgs += '<Callback>'
    strArgs += '</Callback>'
    return strArgs;
}

</script>
</head>
<body id='myBody'>
    <form id="form1" runat="server">
        <atlas:ScriptManager ID="ScriptManager1" 
               runat="server" EnablePartialRendering="True">
        </atlas:ScriptManager>
        <div>
        </div>
        <atlas:UpdatePanel ID="up1" runat="server">
            <ContentTemplate>
                <asp:Calendar ID="Calendar1" runat="server">
                </asp:Calendar>
                Click the calndar for an unknown error!
            </ContentTemplate>
        </atlas:UpdatePanel>
    </form>
</body>
</html>

Error: Your Callbacks/Postbacks stop working after the first successful Postback (Applies to ATLAS)

This problem may happen when your client scripts are not properly registered back on the client after ATLAS makes a partial postback. To resolve this problem, use the ClientScript object in the Page_Load event to register your client scripts.

protected void Page_Load(object sender, EventArgs e)
{
    if (IsCallback)
    {
        // You don't need to re-register your
        // scripts on each Callback
        // For Callbacks,you only do it when
        // you page loads the first time.
    }
    else if (IsPostBack)
    {
        //  Normally You would do your JavaScript
        //  Plumbingthis in your initial load and
        //  RaisePostBackEvent but because Atlas
        //  doesn't raise that event you need 
        //  to put it here for Atlas partial Postbacks

        ClientScriptPlumbing();
    }
    else
    {
        // Initilize the Page
        ClientScriptPlumbing();
    }
}
private void ClientScriptPlumbing()
{
    //Register other client functions
    Page.ClientScript.RegisterClientScriptBlock(this.GetType(), 
                                            "CommonScripts", @"
          function foo() {}
              ....
        "
       , true);
}

Conclusion

This article explained how to resolve some of the common issues with ASP.NET ATLAS and client calls. Later in another article, I will discuss the new ATLAS text/xml-script and the ControlExtender toolkit. I will give you some ideas about how to use JavaScript to achieve the same functionality in an easy and comprehensive fashion. You can leave your comments here.

Cheers!