string ExecuteCallbackMethod(string callbackArgument)
{
var controlType = GetType();
// Deserialize the callback JSON into CLR objects
var js = new JavaScriptSerializer();
var callInfo = js.DeserializeObject(callbackArgument) as Dictionary<string, object>;
// Get the call information
var methodName = (string)callInfo["name"];
var args = (object[])callInfo["args"];
var clientState = (string)callInfo["state"];
// Attempt to load the client state
var csm = this as IClientStateManager;
if(csm != null && csm.SupportsClientState)
csm.LoadClientState(clientState);
// call the method
object result = null;
string error = null;
try {
// Find a matching static or instance method. Only public methods can be invoked
var mi = controlType.GetMethod(methodName, BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance);
if(mi == null)
throw new MissingMethodException(controlType.FullName, methodName);
// Verify that the method has the corrent number of parameters as well as the ExtenderControlMethodAttribute
var methodParams = mi.GetParameters();
var methAttr = (ExtenderControlMethodAttribute)Attribute.GetCustomAttribute(mi, typeof(ExtenderControlMethodAttribute));
if(methAttr == null || !methAttr.IsScriptMethod || args.Length != methodParams.Length)
throw new MissingMethodException(controlType.FullName, methodName);
// Convert each argument to the parameter type if possible
// NOTE: I'd rather have the ObjectConverter from within System.Web.Script.Serialization namespace for this
var targetArgs = new object[args.Length];
for(var i = 0; i < targetArgs.Length; i++) {
if(args[i] == null)
continue;
targetArgs[i] = Convert.ChangeType(args[i], methodParams[i].ParameterType, CultureInfo.InvariantCulture);
}
result = mi.Invoke(this, targetArgs);
} catch(Exception ex) {
// Catch the exception information to relay back to the client
if(ex is TargetInvocationException) {
ex = ex.InnerException;
}
error = ex.GetType().FullName + ":" + ex.Message;
}
// return the result
var resultInfo = new Dictionary<string, object>();
if(error == null) {
resultInfo["result"] = result;
if(csm != null && csm.SupportsClientState)
resultInfo["state"] = csm.SaveClientState();
} else {
resultInfo["error"] = error;
}
// Serialize the result info into JSON
return js.Serialize(resultInfo);
}