ServerMethods' exception handling

From Catglobe Wiki
Revision as of 06:44, 18 October 2013 by Wikicatglobe (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

<accesscontrol>Main:MyGroup</accesscontrol>

Introduction

ServerMethods' exception handling for asynchronous server methods has been improved. The improvement will be available from version 5.0 and forward. Should anyone need it for version 4.9, then a merge back to version 4.9 will also be done, but this is only done on request.

In the previous version of ServerMethods there was no easy way of handling exceptions that occurred for asynchronous server methods. If an exception occurred then the message from that exception would be returned to the callback function as a string. So, if your server method already returned a string it would be difficult to see, when the string was an exception and when it was actually the result you wanted.

The Improvements

In order to better handle exceptions for asynchronous server methods we have implemented two new event handlers on the ServerMethods class:

  • ServerMethods.onValidationError
  • ServerMethods.onCallServerError

And a new property on the ServerMethodException class:

  • isException

How to use these new event handlers and properties will be explained in the following sections.

ServerMethods.onValidationError

When a server method is called from the client side, then validation of the arguments passed to the server method is done before actually sending the request to the server side.

If validation of the arguments passed to the server method cannot be validated then ServerMethods.onValidationError is called. A default implementation of this method already exists, and we will show it here as an example of how to implement an event handler for validation errors.

// On validation error event handler
ServerMethods.onValidationError = function(serverMethod, callerArguments)
{
	// Get parameters for the server method
	var parameters = serverMethod.getParameters();
	
	// Validate number of parameters
	if(parameters.length&nbsp;!= callerArguments.length)
	{
		alert("Server method "+serverMethod.getName()+" received an invalid number of arguments");
		return;
	}

	// Validate types
	var messages = "";
	for(var i = 0; i < parameters.length; i++)
	{
		if(!ServerMethods.__validateType(parameters[i].getType(), callerArguments[i]))
		{
			// Some kind of error showing there is a type mismatch
			messages += " - Parameter '"+parameters[i].getName()+
				"' expected type '"+parameters[i].getTypeName()+
				"' not type '"+ (typeof callerArguments[i])+"'";
		}
	}

	if(0 < messages.length)
	{
		messages = "Type mismatch(es) in server method "+serverMethod.getName()+":\n"+messages;
		alert(messages);
		return;
	}
}

The whole page must be loaded before you can change the event handler, so the ServerMethods.onValidationError method could be changed for example when the body fires the onload event. A small example of this is given below:

<%@ Page language="c#" Inherits="CatGlobe.Web.Common.ServerMethods.ServerMethodsTesting" Codebehind="ServerMethodsTesting.aspx.cs">
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<html xmlns="http://www.w3.org/1999/xhtml">
	<head>
		<title>ServerMethods example</title>

		<script type="text/javascript">
			function onPageLoad()
			{
				// On validation error event handler
				ServerMethods.onValidationError = function(serverMethod, callerArguments)
				{
					alert("Validation error");
				}
			}
		</script>
	</head>
	
	<body onload="onPageLoad();">
		<form action="ServerMethodsTesting.aspx" runat="server">
			<!-- html goes here -->
		</form>
	</body>
</html>

ServerMethods.onCallServerError

When a server method is called synchronous we can use a try-catch block around the call to catch exceptions that might have been thrown on the server, but doing so for an asynchronous server method is not possible because JavaScript is not waiting actively for the server side to respond back to the client side.

Therefore we have changed the way that asynchronous server methods inform the client side about exceptions occurred on the server side. When an exception is thrown on the server it is captured by ServerMethods API and ServerMethods.onCallServerError is called.

The default implementation for ServerMethods.onCallServerError method is shown below:

// On error event handler
ServerMethods.onCallServerError = function(exception, serverMethod, callerArguments)
{
	alert(exception.getMessage());
}

It is possible to disable the call to this method as shown in the following example; again overriding this method can only be done after the whole page has been loaded:

<%@ Page language="c#" Inherits="CatGlobe.Web.Common.ServerMethods.ServerMethodsTesting" Codebehind="ServerMethodsTesting.aspx.cs" %>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >

<html xmlns="http://www.w3.org/1999/xhtml">

	<head>
		<title>ServerMethods example</title>

		<script type="text/javascript">
		function onPageLoad()
		{
			ServerMethods.onCallServerError = null;
		}
		</script>
	</head>
	
	<body onload="onPageLoad();">
		<form action="servermethodstesting.aspx" runat="server">
			<!-- html goes here -->
		</form>
	</body>
</html>

When the ServerMethods.onCallServerError is disabled as shown in the example above, then any exception thrown on the server will be send to the client side’s callback function instead. The next section described how it is possible to determine whether the value returned to the callback function is a ServerMethodException or actually the result that was expected.

ServerMethodException.isException

Instead of returning the exception as a string, the exception object ServerMethodException is now passed to the callback function if an exception was caught on the server side. In order to identify that an exception occurred a new property has been added to the ServerMethodException class called isException, so your callback function should look something like this:

function onMyServerMethodCallback(returnValue)
{
	if(returnValue.isException)
	{
		// Do your error handling here
	}

	// Do your normal callback handling here
}

Notice that when exceptions are thrown the callback function is only called if you have disabled the error handler as described in the previous section.