利用Anthem.net 实现前台javascript调用服务器端c#函数 及流程分析
Javascript调用服务器端c#函数(页面函数, 母版函数, 控件函数), 这个功能很早anthem.net就提供了, 且在帮助手册中有相关的例子, 但自己没怎么注意, 今天看同事研究anthem.net时, 突然发现了 . 看来anthem.net给我们留下的发挥空间还是挺大的.
下面举一个简单的例子, 及分析下执行流程.
例子如下:
1. CS定义函数Add
public int Add(int a, int b) { return a + b; }
2. 添加函数的属性, 这样才能在客户端调用他.
[Anthem.Method]
public int Add(int a, int b)
{
return a + b;
}
3. 在页面加载时注册Anthem.Manager
void Page_Load() { Anthem.Manager.Register(this); }
4. 在aspx页面添加以下html控件
<input id="a" size="3" value="1" />
<input id="b" size="3" value="2" />
<button οnclick="DoAdd(); return false;" type="button">Add</button>
<input id="c" size="6">
5. 添加javascript函数, 用来调用服务器端方法.
<script type="text/javascript">
function DoAdd() {
Anthem_InvokePageMethod(
'Add',
[document.getElementById('a').value, document.getElementById('b').value],
function(result) { document.getElementById('c').value = result.value; }
);
}
</script>
6. 第一个参数"add"是服务器端函数名称
Anthem_InvokePageMethod(
'Add',
[document.getElementById('a').value, document.getElementById('b').value],
function(result) { document.getElementById('c').value = result.value; }
);
7. 第二个参数时传给服务器端函数的参数
Anthem_InvokePageMethod(
'Add',
[document.getElementById('a').value, document.getElementById('b').value],
function(result) { document.getElementById('c').value = result.value; }
);
8. 第三个参数是服务器端函数执行后的回调方法.
Anthem_InvokePageMethod(
'Add',
[document.getElementById('a').value, document.getElementById('b').value,
function(result) { document.getElementById('c').value = result.value; }
);
9. 回调结果result是一个对象, 具有一个value属性和error属性. 如果服务器端函数调用出现错误, 则记录在error中, value是返回服务器端方法的执行结果.
Anthem_InvokePageMethod(
'Add',
[document.getElementById('a').value, document.getElementById('b').value,
function(result) { document.getElementById('c').value = result.value; }
);
转自:http://anthem.talloaksoftware.com/InvokePageMethod.aspx
稍微分析以下执行流程:
前台执行DoAdd()执行 Anthem_InvokePageMethod, 这个函数执行一个anthem callback, 模拟对当前页面进行请求, 具体的流程参见我以前写的一篇分析文章:简略的分析一下Anthem无刷新控件的实现原理和流程
主要用到的相关方法在Manager.cs中
下面的函数用来判断"Add"方法是否具有[Anthem.Method]属性
private static MethodInfo FindTargetMethod(object target, string methodName)
{
Type type = target.GetType();
MethodInfo methodInfo = type.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (methodInfo != null)
{
object[] methodAttributes = methodInfo.GetCustomAttributes(typeof(Anthem.MethodAttribute), true);
if (methodAttributes.Length > 0)
{
return methodInfo;
}
}
return null;
}
如果"add"具有具有[Anthem.Method]属性, 就通过反射调用该方法.
if (methodName != null && methodName.Length > 0)
{
MethodInfo methodInfo = FindTargetMethod(targetObject, methodName);
if (methodInfo == null)
{
error = "METHODNOTFOUND";
}
else
{
try
{
object[] parameters = ConvertParameters(methodInfo, req);
val = InvokeMethod(targetObject, methodInfo, parameters);
}
catch (MethodAccessException ex)
{
if (!methodInfo.IsPublic)
error = string.Format("Anthem.Manager does not have permission to invoke method \"{0}\" in the current trust level. Please try making the method Public.", methodName);
else
error = ex.Message;
}
catch (Exception ex)
{
error = ex.Message;
}
}
}