CURRENT PROJECTS
loading
_a=%5B%27first%27%2C%27second%27%5D&_f=com.overset.Util.echoArgs_a serves as the JSON serialized argument array of strings, i.e. ['arg1','arg2']
{"_s":"","_m":"","_d":""}
_s Is the status of the function response; ["OK","ERR"]
<%@ Page Language="C#" AutoEventWireup="true" Trace="false" Debug="false" EnableSessionState="false" ValidateRequest="false" %>
<%@ Assembly Name = "LitJson" %>
<%@ Import Namespace = "LitJson" %>
<%@ Import Namespace = "System.Globalization" %>
<%@ Import Namespace = "System.Reflection" %>
<script runat="server">
/// <summary>
/// container class to instantiate the core return structure
/// </summary>
public class ajaxReturnStruct {
public Hashtable retStr = new Hashtable();
public ajaxReturnStruct (string ajaxStatus, object ajaxData) {
this.retStr["_s"] = ajaxStatus;
this.retStr["_d"] = ajaxData;
this.retStr["_m"] = "";
}
public ajaxReturnStruct (string ajaxStatus, object ajaxData, string ajaxMessage) {
this.retStr["_s"] = ajaxStatus;
this.retStr["_d"] = ajaxData;
this.retStr["_m"] = ajaxMessage;
}
}
/// <summary>
/// new custom Exception class so that we can properly handle exceptions from remote reflection method calls
/// </summary>
public class ajaxException : Exception {
public string ajaxStatus;
public string stackTrace;
public ajaxException() {
this.ajaxStatus = "err";
this.stackTrace = "";
}
public ajaxException(string ajaxMessage) : base(ajaxMessage) {
this.ajaxStatus = "err";
this.stackTrace = "";
}
public ajaxException(string ajaxExStatus, string ajaxExMessage) : base(ajaxExMessage) {
this.ajaxStatus = ajaxExStatus;
this.stackTrace = "";
}
public ajaxException(string ajaxExStatus, string ajaxExData, string ajaxExMessage) : base(ajaxExMessage) {
this.ajaxStatus = ajaxExStatus;
this.stackTrace = ajaxExData;
}
}
/// <summary>
/// This is the core Page_Load function that drives the AJAX handling of remote methods via reflection
/// </summary>
protected void Page_Load(object sender, System.EventArgs e) {
if ( Request.Form["_f"] != null && Request.Form["_a"] != null ) {
string[] assmQNameArray;
string assmQName;
JsonData parseData;
Type dynType;
object foundObj;
Hashtable invokeMeth;
string catchMethName;
object[] invArgs = new object[1];
// instantiate the correct [namespace.assembly.method,assembly] via reflection
try {
// now parse actual data from JSON to native .net object
parseData = JsonMapper.ToObject(Request.Form["_a"]);
// fetch the AssemblyQualifiedName from the function string in the POST vars
assmQNameArray = Request.Form["_f"].Split(".".ToCharArray());
assmQName = String.Join(".", assmQNameArray, 0, (assmQNameArray.Length - 1) );
// attempt to find function - throw on error and ignore case
dynType = Type.GetType(assmQName + "," + assmQName, true, true);
// create instance of Type found - nonPublic=true
foundObj = Activator.CreateInstance(dynType, true);
} catch (Exception cEx) {
throw(new ajaxException("err", "Cannot find dynamic function -- " + cEx.Message));
}
// build the arguments array and assume the arguments will always be a string
if ( parseData.IsArray ) {
invArgs = new object[parseData.Count];
for ( int pdI=0; pdI < parseData.Count; pdI++ ) {
if ( parseData[pdI].IsBoolean )
invArgs[pdI] = (bool)parseData[pdI];
if ( parseData[pdI].IsDouble )
invArgs[pdI] = (double)parseData[pdI];
if ( parseData[pdI].IsInt )
invArgs[pdI] = (int)parseData[pdI];
if ( parseData[pdI].IsLong )
invArgs[pdI] = (long)parseData[pdI];
if ( parseData[pdI].IsString )
invArgs[pdI] = (string)parseData[pdI];
}
} else {
throw(new ajaxException("err", "Data must be sent as 1D array of simple data types."));
}
// attempt to execute the remote method via reflection
try {
invokeMeth = (Hashtable) dynType.InvokeMember( assmQNameArray[assmQNameArray.Length - 1], BindingFlags.InvokeMethod, null, foundObj, invArgs );
} catch (TargetInvocationException tie) {
// To discover the real cause of a remote Exception you must catch TargetInvocationException and examine the inner exception.
throw(new ajaxException("err", tie.InnerException.StackTrace.ToString(), "Unexpected error calling dynamic function -- " + tie.InnerException.Message.ToString()));
}
Response.AddHeader("Content-Type", "text/javascript");
// prepend the escaping comments
Response.Write("/****/\n");
// build response envelope
ajaxReturnStruct aRet = new ajaxReturnStruct((string)invokeMeth["_s"], (string)invokeMeth["_d"], (string)invokeMeth["_m"]);
// serialize response envelope and write to the response
Response.Write( JsonMapper.ToJson( aRet.retStr ) );
} else {
throw(new ajaxException("err", "You must include the _f (function) and _a (arguments) arguments in the POST data."));
}
}
/// <summary>
/// This will allow for the Page directive to handle errors and return them to the client in the AJAX+JSON format
/// </summary>
public void Page_Error(object sender, System.EventArgs e) {
Response.Clear();
// ensure we escape any prior sent javascript comments (paranoid)
Response.Write("/****/\n");
ajaxReturnStruct retStr;
// handle the display of our custom ajaxEception object
if ( Server.GetLastError().GetBaseException().GetType() == typeof(ajaxException) ) {
ajaxException objErr = (ajaxException)Server.GetLastError().GetBaseException();
retStr = new ajaxReturnStruct(objErr.ajaxStatus, objErr.stackTrace, objErr.Message.ToString());
} else {
Exception objErr = Server.GetLastError().GetBaseException();
retStr = new ajaxReturnStruct("err", objErr.StackTrace.ToString(), objErr.Message.ToString());
}
Response.AddHeader("Content-Type", "text/javascript");
Response.Write( (string)JsonMapper.ToJson( retStr.retStr ) );
Server.ClearError();
}
</script>
// csc.exe /nologo /t:library /out:Bin\com.overset.Util.dll /r:Bin\LitJson.dll com.overset.Util.cs
namespace com.overset {
using System;
using System.Collections;
using LitJson;
public class Util {
public Hashtable retStr;
/// <summary>
/// constructor creates return structure object
/// </summary>
public Util () {
this.retStr = new Hashtable();
}
/// <summary>
/// sets the data in the RetStruct to a string
/// of the 2 arguments appended together
/// </summary>
public object echoArgs (string arg1, string arg2) {
this.retStr["_s"] = "OK";
this.retStr["_d"] = arg1 + arg2;
this.retStr["_m"] = "";
return this.retStr;
}
}
}
<html>
<head>
<script language="JavaScript" type="text/javascript" src="jquery.js"></script>
<script>
$(document).ready( function () {
$.ajax({
data: '&_f=com.overset.Util.echoArgs&_a=[\'first\',\'second\']',
dataType: 'json',
cache: false,
success: function(result, textStatus) {
alert( 'status: ' + result._s + '\n' +
'data: ' + result._d + '\n' +
'message: ' + result._m);
},
type: 'POST',
url: 'ah.aspx'
});
});
</script>
</head>
</html>
&_f=com.overset.Util.echoArgs&_a=%5B%27first%27%2C%27second%27%5DAnd should get the following response:
Content-Type: text/javascript; charset=utf-8
/****/
{"_s":"OK","_m":"","_d":"firstsecond"}

