ASP.NET Callback – and HOW?

If you try to find ASP.NET Callback sample from your favourite search engine, most probably you will get samples with this method.

ClientScriptManager.GetCallbackEventReference

It is correct that you have to use this method to register the javascript function to handle Callback. With this approach, I found it is not easy to manage if I want to perform Callback in multiple Web User Controls at the same page. And also, personally, I don’t like to write javascript functions in code behind files. Unless I have to. I consider this as Separation of concerns. Open-mouthed smile

By following Implementing Client Callbacks Programmatically Without Postbacks in ASP.NET Web Pages article, I found eventually the Callback method registration will end up with this javascript rendered at client side.

<script type="text/javascript">
//<![CDATA[
function CallServer(arg, context) {WebForm_DoCallback('__Page',arg,ReceiveServerData,"",null,false); }//]]>
</script>

Since thing become clear to me, so I plan to write everything in javascript file. I quickly check what is WebForm_DoCallback and what are the arguments that it demand.

function WebForm_DoCallback(eventTarget, eventArgument, eventCallback, context, errorCallback, useAsync)

All of the arguments are pretty meaningful from the name itself. By comparing these two scripts, I found the only challenge is to figure out what is __Page? After searching & several testing, I can confirm it is UniqueID of the page/web user control. So it end up with this code in my page.

        protected void Page_Init(object sender, EventArgs e)
        {
            String script;

            if (!Page.IsCallback)
            {
                Page.ClientScript.GetCallbackEventReference(this, "", "", "");

                if (!Page.ClientScript.IsClientScriptIncludeRegistered("JQuery"))
                {
                    Page.ClientScript.RegisterClientScriptInclude("JQuery", Page.ResolveUrl("~/Scripts/jquery-1.9.0.js"));
                }

                if (!Page.ClientScript.IsClientScriptIncludeRegistered("Default"))
                {
                    Page.ClientScript.RegisterClientScriptInclude("Default", Page.ResolveUrl("~/Default.js"));
                }

                script = "var _Default = new Default('" + this.ClientID + "','" + UniqueID + "',['_Default','']);";

                //Create the clientscript instance here.
                if (!Page.ClientScript.IsStartupScriptRegistered("_Default_Script"))
                {
                    Page.ClientScript.RegisterStartupScript(this.GetType(), "_Default_Script", script, true);
                }
            }
        }

Why Page_Init event handle, not Page_Load or Page_PreRender. This is because Page_Init raised after all controls have been initialized … For detail, you can refer to ASP.NET Page Life Cycle Overview. When implement with web user controls, sometimes, I need methods in web user controls to be ready for consume when Page ready but never in the other way around.

I still need to include Page.ClientScript.GetCallbackEventReference method. Otherwise, the required resources(javascript) will not include to the page.

script = "var _Default = new Default('" + this.ClientID + "','" + UniqueID + "',['_Default','']);";

Default in this script is my javascript class for this page. It need 3 arguments during initialize. They are:

  • this.ClientID : this argument doesn’t make sense for this page because it doesn’t implement Master Page and not Web User Control. I have another page(Default.aspx in MasterPage folder) in the attached source code which need this argument value to register the event handler for each controls at client side.
  • UniqueID : as I mentioned, I need this argument value for WebForm_DoCallback method.
  • ‘_Default’ : my practice but not using in this sample. You can ignore it.

//cid = ClientID
//uid = UniqueID
//arg =  ClientInstanceName, "".
function Default(cid, uid, arg) {
    var that = this;

    this._uID = uid;
    this._cID = cid;
    this._clientInstanceName = arg[0];

    Default.prototype.GetData = function () {
        var data = new Array();

        data[0] = $("#FirstName")[0].value.toString();
        data[1] = $("#LastName")[0].value.toString();

        return data;
    };

    Default.prototype.UpdateData = function () {
        var arg = new String();

        arg = "UPDATE|" + this.GetData().join("|");

        WebForm_DoCallback(this._uID, arg, this.CallbackResult, null, null, true);
    };

    Default.prototype.CallbackResult = function (arg, context) {
        var data = arg.split("|");

        switch (data[0]) {
            case "UPDATE":
                alert("Callback done!");
                break;

            case "ERROR":
                alert(data[1]);
                break;
        }
    };

    Default.prototype.AddHandler = function () {
        var that = this;

        $("#SubmitButton_Callback").bind("click", function (s, e) {
            that.UpdateData();
        });
    };

    that.AddHandler();
}

Let’s have a look at Default.js file. If you going to ask about this and that, please spend some time on my previous blog post, This and That, and Javascript. Smile

Basically, I register an event handler for submit button click event. So it will execute UpdateData method, to get data and then execute Callback(WebForm_DoCallback) method. After the request travel to server and return, it will go the CallbackResult method. This has been registered at the WebForm_DoCallback method.

image

Now look at code behind, when I set a break point in RaiseCallbackEvent handler. I can see what had been passed from Callback method. With this, I can easily code and process these data and update to database. After this handler, the process will goes to GetCallbackResult handler. At this method, I code to check whether need to return result or error message. So that, at client side, I can handle it at CallbackResult method.

So, as you can see. To use Callback at ASP.NET, you have to code more. But it worth to do it if you wish to have a better server performance and a more responsive web site. It also make you have more understanding on ASP.NET.

Download Attachment

Advertisements

ASP.NET Callback – and WHY?

If you are familiar with ASP.NET Web Form development, I think Postback and Callback are not new topics for you. Now, let me show the impact on traffic for each methods.

image

I prepared 3 ways to perform server request for this sample. Each of them represented by a button and they are “Postback”, “Callback” and “Update Panel” (Partial Postback).

For a better illustration, I use Fiddler to capture the traffic. And let see what we have after click on each button.

  • Postback

image

For all the resources including javascript, embedded resources and web page (It can be more which including CSS files, images, media, external link… etc.) will be send to browser again even only one button begin clicked.

  • Callback

image

Not bad. Only web page being updated. With 1,192 bytes sent and 761 bytes received.

  • Update Panel

image

This one also not bad. Only web page being updated. With 1,319 bytes sent and 1,266 bytes received (As I only wrap one set of First Name, Last Name & Button controls in the Update Panel).

After this experiment, let me explain why the traffic is different for each different ways to reach server.

  • Postback

All contains of the web page (ViewState, Hidden Controls…etc.) will be send back to the server. During the browser process response of the request, it will request all resources again. Like Javascript files, Images, CSS files… .etc.

  • Callback

All contains of the web page (ViewState, Hidden Controls…etc.) will be send back to the server. Here I have to highlight one thing, ViewState objects do travel back to server but you are not able to modify any value of controls. This is because the page life cycle for Callback doesn’t include SaveViewState and Render events. For detail, you can refer to Brij Bhushan Mishra’s blog – Exploring Client Callback

  • Update Panel

All contains of the web page (ViewState, Hidden Controls…etc.) will be send back to the server. But what had been return in the response package is only content of the area that I put into the Update Panel Content Template. The page life cycle for this request is the same as Postback but just it will not refresh/update for the controls out of the Update Panel.

Summary

Postback: is the easiest way to program by using ASP.NET Web Form but It will make the traffic from server becomes heavy.

Callback: not easy to implement if compare among the other two. But it produce light traffic from server and return only what the request need.

Update Panel: not hard to implement but I suggest you to read Dave Ward’s blog – Why ASP.NET AJAX UpdatePanels are dangerous and have more understand on how it works before you consider to implement this.