How to implement AJAX callbacks on your page

1. Enable AJAX call backs by implementing (inheriting) the ICallbackEventHandler.

Add the class inheritance:

: ICallbackEventHandler
or
, ICallbackEventHandler // if there already is an inheritance
to the end of the class definition
2. This means that you must implement two further functions in the class:

#region ICallbackEventHandler Members

    public string  GetCallbackResult()
    {
        return  _callbackResult;
    }

    public void  RaiseCallbackEvent(string eventArgument)
    {
        _callbackResult = YourOwnFunc(eventArgument);
    }

#endregion

GetCallbackResult() allows you to access the result of the callback
RaiseCallbackEvent() is the method called by the AJAX call, this should call out to your own c# method in this class YourOwnFunc() which needs to receive a string as a parameter.

3. Don't forget to declare the text string at the top:

private string _callbackResult;
4. Now you have to inject a javascript function into the page which will be called whenever you wish to call the AJAX method. (in this case I've called it callCallback) - this is to be triggered by the button push, form element change, click etc detected by JavaScript. This C# injection populates this function with a call to the actual AJAX call, which we get the name of by allowing C# to tell us with the Page.ClientScript.GetCallbackEventReference function. In a real application, here is where you would also trigger any 'loading...' formatting while waiting for the result to return.

string cbr = @"function callCallback(thisParam) { "  +
       Page.ClientScript.GetCallbackEventReference(this, "thisParam", "receiveResult",
       null, null, true) + "; }";
Page.ClientScript.RegisterClientScriptBlock(typeof(Page), "postback", cbr, true);
The parameter thisParam passed into the callback must be a string. If an int, float, or array needs to be passed to the server, it must be serialised into a string first in JavaScript before passing in (JSON is handy for passing complex objects about, or you can just do a bar|separated|string if it's simple). receiveResult is the name of the JavaScript function which is to process the result when it asynchronously comes back from the server.
5. Now you have to write the corresponding receiveResult onto the page in JavaScript. In a real application, this would take the result and populate a field or a div with the result, and also remove any 'loading...' formatting you applied when calling the AJAX method in the first place.. To test, here I just alert the result.

<script type="text/javascript" language="javascript">

function receiveResult(theResult)
{
  alert(theResult);
}

</script>
6. In the example above, a simple text string is sent back and displayed on screen with an alert. Obviously any string can be sent back, including HTML. This means that if we can regenerate the HTML of controls or groups of controls, then this could be sent back, and replace the existing HTML on the page. This is what UpdatePanel does behind the scenes, but doing it yourself is a good way to understand and get around its limitations.

If we had a DataGrid on the page which was bound to a database query result, and we wanted to modify the order, or apply a filter, we can do that in the codebehind as we would normally in a normal postback clickhandler. Unlike with a normal click handler, the page isn't being re-rendered, so we need to manually re-render the DataGrid, get the generated HTML and send that back to the client. To render a control and get the HTML, use this:

    protected string RenderMyControl(DataGrid dg) // or any Control
    {
        string strOutput = "";
        using (System.IO.StringWriter sw = new System.IO.StringWriter())
        {
            using (HtmlTextWriter htw = new HtmlTextWriter(sw))
            {
                dg.RenderControl(htw);
                htw.Flush();
                strOutput = sw.ToString();
            }
        }
        return strOutput;
    }
Then by changing the javascript handling function to something like:
function receiveResult(theResult)
{
  document.getElementById("MyGridContainer").innerHTML = theResult;
}

We can replace the existing DataGrid on the page with the new re-ordered/filtered HTML representing the true rendered HTML of the real codebehind DataGrid. This HTML, being generated by .Net is completely compatible with the page events etc and will postback as normal.

Remember, ANY control can be rendered, and its child controls will be automatically rendered too, so it would be possible to replace an entire page or part of a page as long as the controls are nested in a asp:Panel or some other top-level container. Just Render the top level control and all the child controls will render automatically, giving you the entire HTML to be posted back to the client.

And that is all there is! When you trigger the callCallback(thisParam) function, the corresponding function on the server YourOwnFunc(eventArgument) is called, which can access databases, etc and return a result which is handled by the receiveResult(theResult) function on the client, which does whatever changes to the page are required. By rendering some or all of the controls in the code behind, true HTML can be regenerated and sent back via AJAX to replace the front end HTML.