本文主要逐步介绍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)
        
{
        
//省略
                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;
                                }

                            }

                        }

                    }

                }


                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;

        
//省略

            }

        }


4、CallBackFilter为一个继承Stream的类,主要调用Anthem.Manager.WriteResult方法来获取输出内容
internal class CallBackFilter : Stream
    
{
        
private Anthem.Manager _manager;
        
private Stream _next;
        
private MemoryStream _buffer;

        
//让_next持有当前输出流的引用,然后改变_next的内容输出
        internal CallBackFilter(Anthem.Manager manager, Stream next)
        
{
            _manager 
= manager;
            _next 
= next;
            _buffer 
= new MemoryStream();
        }


        
public override void Close()
        
{
           
//改变输出内容
            _manager.WriteResult(_next, _buffer);
            
base.Close();
        }





    }

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, nullnullnullnullnull);
            }


            
// 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>";
            }


            
byte[] buffer = HttpContext.Current.Response.ContentEncoding.GetBytes(response);
            stream.Write(buffer, 
0, buffer.Length);
}

由于本人技术有限,如有错误之处,请各位多指教!
posted on 2008-01-06 13:22  破碎虚空  阅读(1068)  评论(0编辑  收藏  举报