本文主要逐步介绍Anthem.net后台是如何处理的。由于篇幅有限,在本文中所贴出的方法均只列出重点地方,如需一窥全貌请各位读者自行到原码中查找。
1、我们知道需要使用前台Javascript中可以调用后台方法必须加Page_Load中注册本页
protected
void
Page_Load(
object
sender, EventArgs e)
{
Anthem.Manager.Register(this);
}
2、实际上Anthem.Manager.Register(this),通过调用Manager:AddManager(Page) 方法进行事件绑定。
private
static
void
AddManager(Page page)
{
Manager manager = HttpContext.Current.Items[GetAnthemManagerKey()] as Manager;
if (manager == null)
{
manager = new Manager();
page.PreRender += new EventHandler(manager.OnPreRender);
page.Error += new EventHandler(manager.OnError);
page.Unload += new EventHandler(manager.OnUnload);
manager._targets[GetAnthemManagerKey()] = manager;
HttpContext.Current.Items[GetAnthemManagerKey()] = manager;
}
manager.RegisterPageScript(page);
}
3、这样在页面呈现时就会调用Manager:OnPreRender方法,而OnPreRender方法中通过改变HttpRespnose.Filter的输出。
private
void
OnPreRender(object source, EventArgs e)
{
//省略![](https://www.cnblogs.com/Images/dot.gif)
if (invokeMethod)
{
if (targetObject == null)
{
error = "CONTROLNOTFOUND";
}
else
{
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;
}
}
}
}
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
ConfigureResponse(resp);
//改变当前Response流出的的内容
resp.Filter = new CallBackFilter(this, resp.Filter);
_value = val;
_error = error;
_updatePage = string.Compare(req["Anthem_UpdatePage"], "true", true) == 0;
_updateValidationScripts = false;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
//省略![](https://www.cnblogs.com/Images/dot.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
}
4、CallBackFilter为一个继承Stream的类,主要调用Anthem.Manager.WriteResult方法来获取输出内容
internal
class
CallBackFilter : Stream
{
private Anthem.Manager _manager;
private Stream _next;
private MemoryStream _buffer;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
//让_next持有当前输出流的引用,然后改变_next的内容输出
internal CallBackFilter(Anthem.Manager manager, Stream next)
{
_manager = manager;
_next = next;
_buffer = new MemoryStream();
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
public override void Close()
{
//改变输出内容
_manager.WriteResult(_next, _buffer);
base.Close();
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
}
internal
void
WriteResult(Stream stream, MemoryStream htmlBuffer)
{
StringBuilder sb = new StringBuilder();
try
{
WriteValueAndError(sb, _value, _error, viewState, viewStateEncrypted, eventValidation, controls, scripts);
}
catch (Exception ex)
{
// If an exception was thrown while formatting the
// result value, we need to discard whatever was
// written and start over with nothing but the error
// message.
sb.Length = 0;
//写入输出数据
WriteValueAndError(sb, null, ex.Message, null, null, null, null, null);
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
// If an IOFrame was used to make this callback, then wrap the response in a <textarea> element
// so the iframe will not mess with the text of the JSON object.
string response = sb.ToString();
if (string.Compare(HttpContext.Current.Request["Anthem_IOFrame"], "true", true) == 0)
{
// If the response text contains any </textarea> tags they will truncate the response
// on the client. To avoid this, </textarea> tags are converted to </anthemarea> tags
// here and converted back to </textarea> on the client.
response = "<textarea id=\"response\">" + Regex.Replace(response, "</textarea>", "</anthemarea>", RegexOptions.IgnoreCase) + "</textarea>";
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
byte[] buffer = HttpContext.Current.Response.ContentEncoding.GetBytes(response);
stream.Write(buffer, 0, buffer.Length);
}
由于本人技术有限,如有错误之处,请各位多指教!