AjaxProcHelper.cs
上传用户:szgaoree
上传日期:2009-01-05
资源大小:74k
文件大小:8k
- /*
- * MS 06-04-13 changed content type to "application/json; charset=utf-8"
- *
- *
- *
- */
- using System;
- using System.Reflection;
- using System.Web;
- using System.Web.Caching;
- using System.IO;
- namespace AjaxPro
- {
- internal class AjaxProcHelper
- {
- private IAjaxProcessor p;
- private ImDone done;
- private IntPtr token = IntPtr.Zero;
- private System.Security.Principal.WindowsImpersonationContext winctx = null;
- internal AjaxProcHelper(IAjaxProcessor p)
- {
- this.p = p;
- }
- internal AjaxProcHelper(IAjaxProcessor p, ImDone done, IntPtr token) : this(p)
- {
- this.done = done;
- this.token = token;
- }
- internal void Run()
- {
- if(p.Context.Trace.IsEnabled) p.Context.Trace.Write(Constant.AjaxID, "Begin ProcessRequest");
- try
- {
- // If we are using the async handler we have to set the ASPNET username
- // to have the same user rights for the created thread.
- if(token != IntPtr.Zero)
- winctx = System.Security.Principal.WindowsIdentity.Impersonate(token);
- // We will check the custom attributes and try to invoke the method.
-
- p.Context.Response.Expires = 0;
- p.Context.Response.Cache.SetCacheability(System.Web.HttpCacheability.NoCache);
- p.Context.Response.AddHeader("Content-Type", "application/json; charset=utf-8");
- if(!p.IsValidAjaxToken(Utility.CurrentAjaxToken))
- {
- p.SerializeObject(new System.Security.SecurityException("The Ajax-token is not valid."));
- if(p.Context.Trace.IsEnabled) p.Context.Trace.Write(Constant.AjaxID, "End ProcessRequest");
- return;
- }
- AjaxMethodAttribute[] ma = (AjaxMethodAttribute[])p.Method.GetCustomAttributes(typeof(AjaxMethodAttribute), true);
- AjaxServerCacheAttribute[] sca = (AjaxServerCacheAttribute[])p.Method.GetCustomAttributes(typeof(AjaxServerCacheAttribute), true);
- object[] po = null;
- object res = null;
- #region Retreive Parameters from the HTTP Request
- try
- {
- // The IAjaxProcessor will read the values either form the
- // request URL or the request input stream.
- po = p.RetreiveParameters();
- }
- catch(Exception ex)
- {
- p.SerializeObject(ex);
- if(p.Context.Trace.IsEnabled) p.Context.Trace.Write(Constant.AjaxID, "End ProcessRequest");
- return;
- }
- #endregion
- // if(ca.Length > 0)
- // {
- // if(ca[0].IsClientCacheEnabled)
- // {
- // p.Context.Response.Cache.SetCacheability(System.Web.HttpCacheability.Public);
- // p.Context.Response.Cache.SetExpires(DateTime.Now.Add(ca[0].ClientCacheDuration));
- // }
- // }
- string cacheKey = p.Type.FullName + "|" + p.GetHashCode();
- if(p.Context.Cache[cacheKey] != null)
- {
- if(p.Context.Trace.IsEnabled) p.Context.Trace.Write(Constant.AjaxID, "Using cached result");
- p.Context.Response.Write(p.Context.Cache[cacheKey]);
- if(p.Context.Trace.IsEnabled) p.Context.Trace.Write(Constant.AjaxID, "End ProcessRequest");
- return;
- }
- #region Reflection part of Ajax.NET
- try
- {
- if(p.Context.Trace.IsEnabled) p.Context.Trace.Write(Constant.AjaxID, "Invoking " + p.Type.FullName + "." + p.Method.Name);
- // If this is a static method we do not need to create an instance
- // of this class. Some classes do not have a default constructor.
- if(p.Method.IsStatic)
- {
- try
- {
- res = p.Type.InvokeMember(
- p.Method.Name,
- System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.InvokeMethod | System.Reflection.BindingFlags.IgnoreCase,
- null, null, po);
- }
- catch(Exception ex)
- {
- if(ex.InnerException != null)
- p.SerializeObject(ex.InnerException);
- else
- p.SerializeObject(ex);
- if(p.Context.Trace.IsEnabled) p.Context.Trace.Write(Constant.AjaxID, "End ProcessRequest");
- return;
- }
- }
- else
- {
- // Create an instance of the class using the default constructor that will
- // not need any argument. This can be a problem, but currently I have no
- // idea on how to specify arguments for the constructor.
- if(p.Context.Trace.IsEnabled) p.Context.Trace.Write(Constant.AjaxID, "Reflection Start");
- try
- {
- object c = (object)Activator.CreateInstance(p.Type, new object[]{});
- // Because the page context properties (Request, Response, Cache...) are
- // not set using Reflection we will set the context by using the IContextInitializer
- // interface.
- if(typeof(IContextInitializer).IsAssignableFrom(p.Type))
- {
- ((IContextInitializer)c).InitializeContext(p.Context);
- }
- if(c != null)
- {
- // if(po == null)
- // po = new object[p.Method.GetParameters().Length];
- res = p.Method.Invoke(c, po);
- }
- }
- catch(Exception ex)
- {
- if(ex.InnerException != null)
- p.SerializeObject(ex.InnerException);
- else
- p.SerializeObject(ex);
- if(p.Context.Trace.IsEnabled) p.Context.Trace.Write(Constant.AjaxID, "End ProcessRequest");
- return;
- }
- if(p.Context.Trace.IsEnabled) p.Context.Trace.Write(Constant.AjaxID, "Reflection End");
- }
- }
- catch(Exception ex)
- {
- if(ex.InnerException != null)
- p.SerializeObject(ex.InnerException);
- else
- p.SerializeObject(ex);
- if(p.Context.Trace.IsEnabled) p.Context.Trace.Write(Constant.AjaxID, "End ProcessRequest");
- return;
- }
- #endregion
- try
- {
- if(res != null && res.GetType() == typeof(System.Xml.XmlDocument))
- {
- // If the return value is XmlDocument we will return it direct
- // without any convertion. On the client-side function we can
- // use .responseXML or .xml.
- p.Context.Response.ContentType = "text/xml";
- ((System.Xml.XmlDocument)res).Save(p.Context.Response.OutputStream);
- if(p.Context.Trace.IsEnabled) p.Context.Trace.Write(Constant.AjaxID, "End ProcessRequest");
- return;
- }
- string result = null;;
- System.Text.StringBuilder sb = new System.Text.StringBuilder();
- try
- {
- result = p.SerializeObject(res);
- }
- catch(Exception ex)
- {
- p.SerializeObject(ex);
- if(p.Context.Trace.IsEnabled) p.Context.Trace.Write(Constant.AjaxID, "End ProcessRequest");
- return;
- }
- if(sca.Length > 0)
- {
- if(sca[0].IsCacheEnabled)
- {
- p.Context.Cache.Add(p.Type.FullName + "|" + p.GetHashCode(), result, null, DateTime.Now.Add(sca[0].CacheDuration), System.Web.Caching.Cache.NoSlidingExpiration, System.Web.Caching.CacheItemPriority.Normal, null);
- p.Context.Trace.Write(Constant.AjaxID, "Adding result to cache for " + sca[0].CacheDuration.TotalSeconds + " seconds (HashCode = " + p.GetHashCode().ToString() + ")");
- }
- }
- if(p.Context.Trace.IsEnabled)
- {
- p.Context.Trace.Write(Constant.AjaxID, "Result (maybe encrypted): " + result);
- p.Context.Trace.Write(Constant.AjaxID, "End ProcessRequest");
- }
- }
- catch(Exception ex)
- {
- p.Context.Response.Write(p.SerializeObject(ex));
- if(p.Context.Trace.IsEnabled) p.Context.Trace.Write(Constant.AjaxID, "End ProcessRequest");
- return;
- }
-
- }
- catch(Exception ex)
- {
- p.Context.Response.Write(p.SerializeObject(ex));
- if(p.Context.Trace.IsEnabled) p.Context.Trace.Write(Constant.AjaxID, "End ProcessRequest");
- return;
- }
- finally
- {
- if(token != IntPtr.Zero)
- winctx.Undo();
- if(done != null)
- done();
- }
- }
- }
- }