AjaxProcHelper.cs
上传用户:szgaoree
上传日期:2009-01-05
资源大小:74k
文件大小:8k
源码类别:

Ajax

开发平台:

C#

  1. /*
  2.  * MS 06-04-13 changed content type to "application/json; charset=utf-8"
  3.  * 
  4.  * 
  5.  * 
  6.  */
  7. using System;
  8. using System.Reflection;
  9. using System.Web;
  10. using System.Web.Caching;
  11. using System.IO;
  12. namespace AjaxPro
  13. {
  14. internal class AjaxProcHelper
  15. {
  16. private IAjaxProcessor p;
  17. private ImDone done;
  18. private IntPtr token = IntPtr.Zero;
  19. private System.Security.Principal.WindowsImpersonationContext winctx = null;
  20. internal AjaxProcHelper(IAjaxProcessor p)
  21. {
  22. this.p = p;
  23. }
  24. internal AjaxProcHelper(IAjaxProcessor p, ImDone done, IntPtr token) : this(p)
  25. {
  26. this.done = done;
  27. this.token = token;
  28. }
  29. internal void Run()
  30. {
  31. if(p.Context.Trace.IsEnabled) p.Context.Trace.Write(Constant.AjaxID, "Begin ProcessRequest");
  32. try
  33. {
  34. // If we are using the async handler we have to set the ASPNET username
  35. // to have the same user rights for the created thread.
  36. if(token != IntPtr.Zero)
  37. winctx = System.Security.Principal.WindowsIdentity.Impersonate(token);
  38. // We will check the custom attributes and try to invoke the method.
  39. p.Context.Response.Expires = 0;
  40. p.Context.Response.Cache.SetCacheability(System.Web.HttpCacheability.NoCache);
  41. p.Context.Response.AddHeader("Content-Type", "application/json; charset=utf-8");
  42. if(!p.IsValidAjaxToken(Utility.CurrentAjaxToken))
  43. {
  44. p.SerializeObject(new System.Security.SecurityException("The Ajax-token is not valid."));
  45. if(p.Context.Trace.IsEnabled) p.Context.Trace.Write(Constant.AjaxID, "End ProcessRequest");
  46. return;
  47. }
  48. AjaxMethodAttribute[] ma = (AjaxMethodAttribute[])p.Method.GetCustomAttributes(typeof(AjaxMethodAttribute), true);
  49. AjaxServerCacheAttribute[] sca = (AjaxServerCacheAttribute[])p.Method.GetCustomAttributes(typeof(AjaxServerCacheAttribute), true);
  50. object[] po = null;
  51. object res = null;
  52. #region Retreive Parameters from the HTTP Request
  53. try
  54. {
  55. // The IAjaxProcessor will read the values either form the 
  56. // request URL or the request input stream.
  57. po = p.RetreiveParameters();
  58. }
  59. catch(Exception ex)
  60. {
  61. p.SerializeObject(ex);
  62. if(p.Context.Trace.IsEnabled) p.Context.Trace.Write(Constant.AjaxID, "End ProcessRequest");
  63. return;
  64. }
  65. #endregion 
  66. // if(ca.Length > 0)
  67. // {
  68. // if(ca[0].IsClientCacheEnabled)
  69. // {
  70. // p.Context.Response.Cache.SetCacheability(System.Web.HttpCacheability.Public);
  71. // p.Context.Response.Cache.SetExpires(DateTime.Now.Add(ca[0].ClientCacheDuration));
  72. // }
  73. // }
  74. string cacheKey = p.Type.FullName + "|" + p.GetHashCode();
  75. if(p.Context.Cache[cacheKey] != null)
  76. {
  77. if(p.Context.Trace.IsEnabled) p.Context.Trace.Write(Constant.AjaxID, "Using cached result");
  78. p.Context.Response.Write(p.Context.Cache[cacheKey]);
  79. if(p.Context.Trace.IsEnabled) p.Context.Trace.Write(Constant.AjaxID, "End ProcessRequest");
  80. return;
  81. }
  82. #region Reflection part of Ajax.NET
  83. try
  84. {
  85. if(p.Context.Trace.IsEnabled) p.Context.Trace.Write(Constant.AjaxID, "Invoking " + p.Type.FullName + "." + p.Method.Name);
  86. // If this is a static method we do not need to create an instance
  87. // of this class. Some classes do not have a default constructor.
  88. if(p.Method.IsStatic)
  89. {
  90. try
  91. {
  92. res = p.Type.InvokeMember(
  93. p.Method.Name,
  94. System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.InvokeMethod | System.Reflection.BindingFlags.IgnoreCase,
  95. null, null, po);
  96. }
  97. catch(Exception ex)
  98. {
  99. if(ex.InnerException != null)
  100. p.SerializeObject(ex.InnerException);
  101. else
  102. p.SerializeObject(ex);
  103. if(p.Context.Trace.IsEnabled) p.Context.Trace.Write(Constant.AjaxID, "End ProcessRequest");
  104. return;
  105. }
  106. }
  107. else
  108. {
  109. // Create an instance of the class using the default constructor that will
  110. // not need any argument. This can be a problem, but currently I have no
  111. // idea on how to specify arguments for the constructor.
  112. if(p.Context.Trace.IsEnabled) p.Context.Trace.Write(Constant.AjaxID, "Reflection Start");
  113. try
  114. {
  115. object c = (object)Activator.CreateInstance(p.Type, new object[]{});
  116. // Because the page context properties (Request, Response, Cache...) are 
  117. // not set using Reflection we will set the context by using the IContextInitializer
  118. // interface.
  119. if(typeof(IContextInitializer).IsAssignableFrom(p.Type))
  120. {
  121. ((IContextInitializer)c).InitializeContext(p.Context);
  122. }
  123. if(c != null)
  124. {
  125. // if(po == null)
  126. // po = new object[p.Method.GetParameters().Length];
  127. res = p.Method.Invoke(c, po);
  128. }
  129. }
  130. catch(Exception ex)
  131. {
  132. if(ex.InnerException != null)
  133. p.SerializeObject(ex.InnerException);
  134. else
  135. p.SerializeObject(ex);
  136. if(p.Context.Trace.IsEnabled) p.Context.Trace.Write(Constant.AjaxID, "End ProcessRequest");
  137. return;
  138. }
  139. if(p.Context.Trace.IsEnabled) p.Context.Trace.Write(Constant.AjaxID, "Reflection End");
  140. }
  141. }
  142. catch(Exception ex)
  143. {
  144. if(ex.InnerException != null)
  145. p.SerializeObject(ex.InnerException);
  146. else
  147. p.SerializeObject(ex);
  148. if(p.Context.Trace.IsEnabled) p.Context.Trace.Write(Constant.AjaxID, "End ProcessRequest");
  149. return;
  150. }
  151. #endregion
  152. try
  153. {
  154. if(res != null && res.GetType() == typeof(System.Xml.XmlDocument))
  155. {
  156. // If the return value is XmlDocument we will return it direct
  157. // without any convertion. On the client-side function we can
  158. // use .responseXML or .xml.
  159. p.Context.Response.ContentType = "text/xml";
  160. ((System.Xml.XmlDocument)res).Save(p.Context.Response.OutputStream);
  161. if(p.Context.Trace.IsEnabled) p.Context.Trace.Write(Constant.AjaxID, "End ProcessRequest");
  162. return;
  163. }
  164. string result = null;;
  165. System.Text.StringBuilder sb = new System.Text.StringBuilder();
  166. try
  167. {
  168. result = p.SerializeObject(res);
  169. }
  170. catch(Exception ex)
  171. {
  172. p.SerializeObject(ex);
  173. if(p.Context.Trace.IsEnabled) p.Context.Trace.Write(Constant.AjaxID, "End ProcessRequest");
  174. return;
  175. }
  176. if(sca.Length > 0)
  177. {
  178. if(sca[0].IsCacheEnabled)
  179. {
  180. 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);
  181. p.Context.Trace.Write(Constant.AjaxID, "Adding result to cache for " + sca[0].CacheDuration.TotalSeconds + " seconds (HashCode = " + p.GetHashCode().ToString() + ")");
  182. }
  183. }
  184. if(p.Context.Trace.IsEnabled)
  185. {
  186. p.Context.Trace.Write(Constant.AjaxID, "Result (maybe encrypted): " + result);
  187. p.Context.Trace.Write(Constant.AjaxID, "End ProcessRequest");
  188. }
  189. }
  190. catch(Exception ex)
  191. {
  192. p.Context.Response.Write(p.SerializeObject(ex));
  193. if(p.Context.Trace.IsEnabled) p.Context.Trace.Write(Constant.AjaxID, "End ProcessRequest");
  194. return;
  195. }
  196. }
  197. catch(Exception ex)
  198. {
  199. p.Context.Response.Write(p.SerializeObject(ex));
  200. if(p.Context.Trace.IsEnabled) p.Context.Trace.Write(Constant.AjaxID, "End ProcessRequest");
  201. return;
  202. }
  203. finally
  204. {
  205. if(token != IntPtr.Zero)
  206. winctx.Undo();
  207. if(done != null)
  208. done();
  209. }
  210. }
  211. }
  212. }