One of the features in ASP.Net is the ability to call server-side code from client-side code without postback, using something called a client callback. There's a couple of minor caveats I've found so far though :-
- it uses XmlHttp which is IE only at the moment. Firefox and other browsers have an alternative, but the callbacks are using this only.
- the only type you can return from the server is a string (but we can get around that by serializing if necessary)
The example I've used is where I have two related textboxes that need to be kept in sync. If the ClientID box is changed, the ClientName box should display the name of the client that has that ID, and vice-versa.
To start using this functionality, ensure your code-behind implements the ICallbackEventHandler interface :-
public partial class WebForm1 : System.Web.UI.Page, ICallbackEventHandler
Next, I register my callback methods in the Page_Load method in my aspx.cs :-
// Set up client callbacks. These allow client-side scripts to call
// server-side functions and retrieve the results. Its a string-only
// return I'm afraid, limited by the ICallbackEventHandler method signatures
txtClientID.Attributes.Add("onchange", "GetClientNameById('id|' + this.value, 'id');");
string callBackClientID = Page.ClientScript.GetCallbackEventReference(this, "arg", "ClientNameCallback", "context", "ClientNameCallbackError", true);
string clientIDfunction = "function GetClientNameById(arg,context) { " + callBackClientID + "; }";
Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "GetClientNameById", clientIDfunction, true);
txtClientName.Attributes.Add("onchange", "GetClientIdByName('name|' + this.value, 'name');");
string callBackClientName = Page.ClientScript.GetCallbackEventReference(this, "arg", "ClientIdCallback", "context", "ClientIdCallbackError", true);
string clientNamefunction = "function GetClientIdByName(arg, context) { " + callBackClientName + "; }";
Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "GetClientIdByName", clientNamefunction, true);
This registers the server functions with the page and hooks them up to the client callback methods - these callback methods are basic placeholders that do nothing but give the server somewhere to return its string to. So on the aspx page itself :-
<script type="text/javascript">
function ClientNameCallback(result, context)
{
//sorry about the hardcoded element name...
if(result != "")
document.getElementById('ctl00_ContentPlaceHolder1_txtClientName').setAttribute('value',result);
}
function ClientIdCallback(result,context)
{
//sorry about the hardcoded element name...
if(result != "")
document.getElementById('ctl00_ContentPlaceHolder1_txtClientID').setAttribute('value',result);
}
function ClientNameCallbackError(result, context)
{
//Not sure what error is likely to arise at this point, but...
alert('Error in client name callback function - please say that to eSolutions!');
}
function ClientIdCallbackError(result, context)
{
//Not sure what error is likely to arise at this point, but...
alert('Error in client id callback function - please say that to eSolutions!');
}
</script>
Finally, we implement the required ICallbackEventHandler, which contains the server-side processing we want to perform :-
string ICallbackEventHandler.GetCallbackResult()
{
return callbackReturnValue;
}
void ICallbackEventHandler.RaiseCallbackEvent(string eventArgument)
{
// eventArgument should be in format field|value,
// e.g., "id|30102" or "name|test client"
// This is because of the "single string" limitations
// of the callback interface
if(eventArgument.StartsWith("name"))
{
//....do lookup to get the id based on the name, from an array or database, or whatever
callbackReturnValue = <string we want to pass back to client-side
}
else if(eventArgument.StartsWith("id"))
etc.
etc.