/// <summary> /// Returns an instance of a class that implements the <see cref="T:System.Web.IHttpHandler"></see> interface. /// </summary> /// <param name="context">An instance of the <see cref="T:System.Web.HttpContext"></see> class that provides references to intrinsic server objects (for example, Request, Response, Session, and Server) used to service HTTP requests.</param> /// <param name="requestType">The HTTP data transfer method (GET or POST) that the client uses.</param> /// <param name="url">The <see cref="P:System.Web.HttpRequest.RawUrl"></see> of the requested resource.</param> /// <param name="pathTranslated">The <see cref="P:System.Web.HttpRequest.PhysicalApplicationPath"></see> to the requested resource.</param> /// <returns> /// A new <see cref="T:System.Web.IHttpHandler"></see> object that processes the request. /// </returns> public IHttpHandler GetHandler(HttpContext context, string requestType, string url, string pathTranslated) { // First of all we want to check what a request is running. There are three different // requests that are made to this handler: // 1) GET core,prototype,converter.ashx which will include the common AJAX communication // 2) GET typename,assemblyname.ashx which will return the AJAX wrapper JavaScript code // 3) POST typename,assemblyname.ashx which will invoke a method. // The first two requests will return the JavaScript code or a HTTP 304 (not changed). string filename = Path.GetFileNameWithoutExtension(context.Request.Path); Type t = null; Exception typeException = null; bool isInTypesList = false; try { if (Utility.Settings != null && Utility.Settings.UrlNamespaceMappings.Contains(filename)) { isInTypesList = true; t = Type.GetType(Utility.Settings.UrlNamespaceMappings[filename].ToString(), true); } if (t == null) t = Type.GetType(filename, true); } catch (Exception ex) { typeException = ex; } switch(requestType) { case "GET": // get the JavaScript files switch(filename.ToLower()) { case "prototype": return new EmbeddedJavaScriptHandler("prototype"); case "core": return new EmbeddedJavaScriptHandler("core"); case "ms": return new EmbeddedJavaScriptHandler("ms"); case "prototype-core": case "core-prototype": return new EmbeddedJavaScriptHandler("prototype,core"); case "core-prototype-converter": return new EmbeddedJavaScriptHandler("prototype,core,converter"); case "converter": return new ConverterJavaScriptHandler(); default: if (typeException != null) { #if(WEBEVENT) string errorText = string.Format(Constant.AjaxID + " Error", context.User.Identity.Name); Management.WebAjaxErrorEvent ev = new Management.WebAjaxErrorEvent(errorText, WebEventCodes.WebExtendedBase + 201, typeException); ev.Raise(); #endif return null; } if (Utility.Settings.OnlyAllowTypesInList == true && isInTypesList == false) return null; return new TypeJavaScriptHandler(t); } case "POST": // invoke the method if (Utility.Settings.OnlyAllowTypesInList == true && isInTypesList == false) return null; IAjaxProcessor[] p = new IAjaxProcessor[2]; p[0] = new XmlHttpRequestProcessor(context, t); p[1] = new IFrameProcessor(context, t); for(int i=0; i<p.Length; i++) { if(p[i].CanHandleRequest) { if (typeException != null) { #if(WEBEVENT) string errorText = string.Format(Constant.AjaxID + " Error", context.User.Identity.Name); Management.WebAjaxErrorEvent ev = new Management.WebAjaxErrorEvent(errorText, WebEventCodes.WebExtendedBase + 200, typeException); ev.Raise(); #endif p[i].SerializeObject(new NotSupportedException("This method is either not marked with an AjaxMethod or is not available.")); return null; } AjaxMethodAttribute[] ma = (AjaxMethodAttribute[])p[i].AjaxMethod.GetCustomAttributes(typeof(AjaxMethodAttribute), true); bool useAsync = false; HttpSessionStateRequirement sessionReq = HttpSessionStateRequirement.ReadWrite; if (Utility.Settings.OldStyle.Contains("sessionStateDefaultNone")) sessionReq = HttpSessionStateRequirement.None; if(ma.Length > 0) { useAsync = ma[0].UseAsyncProcessing; if(ma[0].RequireSessionState != HttpSessionStateRequirement.UseDefault) sessionReq = ma[0].RequireSessionState; } switch (sessionReq) { case HttpSessionStateRequirement.Read: if (!useAsync) return new AjaxSyncHttpHandlerSessionReadOnly(p[i]); else return new AjaxAsyncHttpHandlerSessionReadOnly(p[i]); case HttpSessionStateRequirement.ReadWrite: if (!useAsync) return new AjaxSyncHttpHandlerSession(p[i]); else return new AjaxAsyncHttpHandlerSession(p[i]); case HttpSessionStateRequirement.None: if (!useAsync) return new AjaxSyncHttpHandler(p[i]); else return new AjaxAsyncHttpHandler(p[i]); default: if (!useAsync) return new AjaxSyncHttpHandlerSession(p[i]); else return new AjaxAsyncHttpHandlerSession(p[i]); } } } break; } return null; }
/// <summary> /// Returns an instance of a class that implements the <see cref="T:System.Web.IHttpHandler"></see> interface. /// </summary> /// <param name="context">An instance of the <see cref="T:System.Web.HttpContext"></see> class that provides references to intrinsic server objects (for example, Request, Response, Session, and Server) used to service HTTP requests.</param> /// <param name="requestType">The HTTP data transfer method (GET or POST) that the client uses.</param> /// <param name="url">The <see cref="P:System.Web.HttpRequest.RawUrl"></see> of the requested resource.</param> /// <param name="pathTranslated">The <see cref="P:System.Web.HttpRequest.PhysicalApplicationPath"></see> to the requested resource.</param> /// <returns> /// A new <see cref="T:System.Web.IHttpHandler"></see> object that processes the request. /// </returns> public IHttpHandler GetHandler(HttpContext context, string requestType, string url, string pathTranslated) { // First of all we want to check what a request is running. There are three different // requests that are made to this handler: // 1) GET core,prototype,converter.ashx which will include the common AJAX communication // 2) GET typename,assemblyname.ashx which will return the AJAX wrapper JavaScript code // 3) POST typename,assemblyname.ashx which will invoke a method. // The first two requests will return the JavaScript code or a HTTP 304 (not changed). string filename = Path.GetFileNameWithoutExtension(context.Request.Path); Type t = null; //iiunknown added @16:06 2013/11/9 增加AjaxPro客户端请求对SharePoint的SPContext.Current的支持,方便服务器端Ajax方法能正确定位到当前真正的SharePoint路径下的SPContext.Current,而不需要传递过多的参数去自己构造SharePoint上下文环境。 #region AjaxPro请求的时候构造SPContext传递到当前上下文中。 string siteid = HttpContext.Current.Request.QueryString.Get("siteid"); string webid = HttpContext.Current.Request.QueryString.Get("webid"); string listid = HttpContext.Current.Request.QueryString.Get("listid"); string itemid = HttpContext.Current.Request.QueryString.Get("itemid"); string lcid = HttpContext.Current.Request.QueryString.Get("lcid"); string formmode = HttpContext.Current.Request.QueryString.Get("formmode"); int lcidNum = 2052; if (!string.IsNullOrEmpty(lcid)) { int.TryParse(lcid, out lcidNum); } System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(lcidNum); SPContext spcontext = null; if (!string.IsNullOrEmpty(siteid)) { SPSite site = new SPSite(new Guid(siteid)); if (site != null && !string.IsNullOrEmpty(webid)) { SPWeb web = site.OpenWeb(new Guid(webid)); if (web != null) { spcontext = SPContext.GetContext(HttpContext.Current, int.Parse(itemid), new Guid(listid), web); int fm = int.Parse(formmode); if (fm > 0) { spcontext.FormContext.FormMode = (Microsoft.SharePoint.WebControls.SPControlMode) int.Parse(formmode); } if (HttpContext.Current.Items["HttpHandlerSPSite"] == null) { HttpContext.Current.Items["HttpHandlerSPSite"] = site; } if (HttpContext.Current.Items["HttpHandlerSPWeb"] == null) { HttpContext.Current.Items["HttpHandlerSPWeb"] = web; } } //if (string.IsNullOrEmpty(listid)) //{ // spcontext = SPContext.GetContext(web); //} //else //{ // if (string.IsNullOrEmpty(itemid)) // { // spcontext = SPContext.GetContext(HttpContext.Current, 0, new Guid(listid), web); // } // else // { // spcontext = SPContext.GetContext(HttpContext.Current, int.Parse(itemid), new Guid(listid), web); // } //} } } if (spcontext != null) { //SharePoint获取当前上下文的方法。 //public static SPContext GetContext(HttpContext context) //{ // if (context == null) // { // throw SPUtility.GetStandardArgumentNullException("context"); // } // SPContext context2 = (SPContext) context.Items["DefaultSPContext"]; // if (context2 == null) // { // context2 = new SPContext(context, 0, Guid.Empty, null); // context.Items["DefaultSPContext"] = context2; // string str = DefaultKey(context, null); // context.Items[str] = context2; // } // return context2; //} context.Items["DefaultSPContext"] = spcontext; } #endregion Exception typeException = null; bool isInTypesList = false; try { if (Utility.Settings != null && Utility.Settings.UrlNamespaceMappings.Contains(filename)) { isInTypesList = true; t = Type.GetType(Utility.Settings.UrlNamespaceMappings[filename].ToString(), true); } if (t == null) { t = Type.GetType(filename, true); } } catch (Exception ex) { typeException = ex; } switch (requestType) { case "GET": // get the JavaScript files switch (filename.ToLower()) { case "prototype": return(new EmbeddedJavaScriptHandler("prototype")); case "core": return(new EmbeddedJavaScriptHandler("core")); case "ms": return(new EmbeddedJavaScriptHandler("ms")); case "prototype-core": case "core-prototype": return(new EmbeddedJavaScriptHandler("prototype,core")); case "converter": return(new ConverterJavaScriptHandler()); default: if (typeException != null) { #if (WEBEVENT) string errorText = string.Format(Constant.AjaxID + " Error", context.User.Identity.Name); Management.WebAjaxErrorEvent ev = new Management.WebAjaxErrorEvent(errorText, WebEventCodes.WebExtendedBase + 201, typeException); ev.Raise(); #endif return(null); } if (Utility.Settings.OnlyAllowTypesInList == true && isInTypesList == false) { return(null); } return(new TypeJavaScriptHandler(t)); } case "POST": // invoke the method if (Utility.Settings.OnlyAllowTypesInList == true && isInTypesList == false) { return(null); } IAjaxProcessor[] p = new IAjaxProcessor[2]; p[0] = new XmlHttpRequestProcessor(context, t); p[1] = new IFrameProcessor(context, t); for (int i = 0; i < p.Length; i++) { if (p[i].CanHandleRequest) { if (typeException != null) { #if (WEBEVENT) string errorText = string.Format(Constant.AjaxID + " Error", context.User.Identity.Name); Management.WebAjaxErrorEvent ev = new Management.WebAjaxErrorEvent(errorText, WebEventCodes.WebExtendedBase + 200, typeException); ev.Raise(); #endif p[i].SerializeObject(new NotSupportedException("This method is either not marked with an AjaxMethod or is not available.")); return(null); } AjaxMethodAttribute[] ma = (AjaxMethodAttribute[])p[i].AjaxMethod.GetCustomAttributes(typeof(AjaxMethodAttribute), true); bool useAsync = false; HttpSessionStateRequirement sessionReq = HttpSessionStateRequirement.ReadWrite; if (Utility.Settings.OldStyle.Contains("sessionStateDefaultNone")) { sessionReq = HttpSessionStateRequirement.None; } if (ma.Length > 0) { useAsync = ma[0].UseAsyncProcessing; if (ma[0].RequireSessionState != HttpSessionStateRequirement.UseDefault) { sessionReq = ma[0].RequireSessionState; } } switch (sessionReq) { case HttpSessionStateRequirement.Read: if (!useAsync) { return(new AjaxSyncHttpHandlerSessionReadOnly(p[i])); } else { return(new AjaxAsyncHttpHandlerSessionReadOnly(p[i])); } case HttpSessionStateRequirement.ReadWrite: if (!useAsync) { return(new AjaxSyncHttpHandlerSession(p[i])); } else { return(new AjaxAsyncHttpHandlerSession(p[i])); } case HttpSessionStateRequirement.None: if (!useAsync) { return(new AjaxSyncHttpHandler(p[i])); } else { return(new AjaxAsyncHttpHandler(p[i])); } default: if (!useAsync) { return(new AjaxSyncHttpHandlerSession(p[i])); } else { return(new AjaxAsyncHttpHandlerSession(p[i])); } } } } break; } return(null); }
/// <summary> /// Returns an instance of a class that implements the <see cref="T:System.Web.IHttpHandler"></see> interface. /// </summary> /// <param name="context">An instance of the <see cref="T:System.Web.HttpContext"></see> class that provides references to intrinsic server objects (for example, Request, Response, Session, and Server) used to service HTTP requests.</param> /// <param name="requestType">The HTTP data transfer method (GET or POST) that the client uses.</param> /// <param name="url">The <see cref="P:System.Web.HttpRequest.RawUrl"></see> of the requested resource.</param> /// <param name="pathTranslated">The <see cref="P:System.Web.HttpRequest.PhysicalApplicationPath"></see> to the requested resource.</param> /// <returns> /// A new <see cref="T:System.Web.IHttpHandler"></see> object that processes the request. /// </returns> public IHttpHandler GetHandler(HttpContext context, string requestType, string url, string pathTranslated) { // First of all we want to check what a request is running. There are three different // requests that are made to this handler: // 1) GET core,prototype,converter.ashx which will include the common AJAX communication // 2) GET typename,assemblyname.ashx which will return the AJAX wrapper JavaScript code // 3) POST typename,assemblyname.ashx which will invoke a method. // The first two requests will return the JavaScript code or a HTTP 304 (not changed). string filename = Path.GetFileNameWithoutExtension(context.Request.Path); Type t = null; Exception typeException = null; bool isInTypesList = false; try { if (Utility.Settings != null && Utility.Settings.UrlNamespaceMappings.Contains(filename)) { isInTypesList = true; t = Type.GetType(Utility.Settings.UrlNamespaceMappings[filename].ToString(), true); } if (t == null) { t = Type.GetType(filename, true); } } catch (Exception ex) { typeException = ex; } switch (requestType) { case "GET": // get the JavaScript files switch (filename.ToLower()) { case "prototype": return(new EmbeddedJavaScriptHandler("prototype")); case "core": return(new EmbeddedJavaScriptHandler("core")); case "ms": return(new EmbeddedJavaScriptHandler("ms")); case "prototype-core": case "core-prototype": return(new EmbeddedJavaScriptHandler("prototype,core")); case "converter": return(new ConverterJavaScriptHandler()); default: if (typeException != null) { #if (WEBEVENT) string errorText = string.Format(Constant.AjaxID + " Error", context.User.Identity.Name); Management.WebAjaxErrorEvent ev = new Management.WebAjaxErrorEvent(errorText, WebEventCodes.WebExtendedBase + 201, typeException); ev.Raise(); #endif return(null); } if (Utility.Settings.OnlyAllowTypesInList == true && isInTypesList == false) { return(null); } return(new TypeJavaScriptHandler(t)); } case "POST": // invoke the method if (Utility.Settings.OnlyAllowTypesInList == true && isInTypesList == false) { return(null); } IAjaxProcessor[] p = new IAjaxProcessor[2]; p[0] = new XmlHttpRequestProcessor(context, t); p[1] = new IFrameProcessor(context, t); for (int i = 0; i < p.Length; i++) { if (p[i].CanHandleRequest) { if (typeException != null) { #if (WEBEVENT) string errorText = string.Format(Constant.AjaxID + " Error", context.User.Identity.Name); Management.WebAjaxErrorEvent ev = new Management.WebAjaxErrorEvent(errorText, WebEventCodes.WebExtendedBase + 200, typeException); ev.Raise(); #endif p[i].SerializeObject(new NotSupportedException("This method is either not marked with an AjaxMethod or is not available.")); return(null); } AjaxMethodAttribute[] ma = (AjaxMethodAttribute[])p[i].AjaxMethod.GetCustomAttributes(typeof(AjaxMethodAttribute), true); bool useAsync = false; HttpSessionStateRequirement sessionReq = HttpSessionStateRequirement.ReadWrite; if (Utility.Settings.OldStyle.Contains("sessionStateDefaultNone")) { sessionReq = HttpSessionStateRequirement.None; } if (ma.Length > 0) { useAsync = ma[0].UseAsyncProcessing; if (ma[0].RequireSessionState != HttpSessionStateRequirement.UseDefault) { sessionReq = ma[0].RequireSessionState; } } switch (sessionReq) { case HttpSessionStateRequirement.Read: if (!useAsync) { return(new AjaxSyncHttpHandlerSessionReadOnly(p[i])); } else { return(new AjaxAsyncHttpHandlerSessionReadOnly(p[i])); } case HttpSessionStateRequirement.ReadWrite: if (!useAsync) { return(new AjaxSyncHttpHandlerSession(p[i])); } else { return(new AjaxAsyncHttpHandlerSession(p[i])); } case HttpSessionStateRequirement.None: if (!useAsync) { return(new AjaxSyncHttpHandler(p[i])); } else { return(new AjaxAsyncHttpHandler(p[i])); } default: if (!useAsync) { return(new AjaxSyncHttpHandlerSession(p[i])); } else { return(new AjaxAsyncHttpHandlerSession(p[i])); } } } } break; } return(null); }
/// <summary> /// Runs this instance. /// </summary> 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); // TODO: check why Opera is not working with application/json; // p.Context.Response.AddHeader("Content-Type", "application/json; charset=utf-8"); p.Context.Response.ContentType = p.ContentType; p.Context.Response.ContentEncoding = System.Text.Encoding.UTF8; if (!p.IsValidAjaxToken()) { // TODO: maybe we want to throw a special exception type. p.SerializeObject(new System.Security.SecurityException("The AjaxPro-Token is not valid.")); if (p.Context.Trace.IsEnabled) { p.Context.Trace.Write(Constant.AjaxID, "End ProcessRequest"); } return; } 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 // Check if we have the same request already in our cache. The // cacheKey will be the type and a hashcode from the parameter values. string cacheKey = p.Type.FullName + "|" + p.GetType().Name + "|" + p.AjaxMethod.Name + "|" + 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.AddHeader("X-" + Constant.AjaxID + "-Cache", "server"); // Return the full output of the last cached call 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.AjaxMethod.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.AjaxMethod.IsStatic) { try { //Note: Demand Invocation here! p.DemandInvocation(); res = p.Type.InvokeMember( p.AjaxMethod.Name, System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.InvokeMethod, 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]; //Note: Demand Invocation here! p.DemandInvocation(); res = p.AjaxMethod.Invoke(c, po); } } catch (Exception ex) { #if (WEBEVENT) string errorText = string.Format(Constant.AjaxID + " Error", p.Context.User.Identity.Name); #endif if (ex.InnerException != null) { #if (WEBEVENT) Management.WebAjaxErrorEvent ev = new Management.WebAjaxErrorEvent(errorText, p, po, WebEventCodes.WebExtendedBase + 100, ex.InnerException); ev.Raise(); #endif p.SerializeObject(ex.InnerException); } else { #if (WEBEVENT) Management.WebAjaxErrorEvent ev = new Management.WebAjaxErrorEvent(errorText, p, po, WebEventCodes.WebExtendedBase + 101, ex); ev.Raise(); #endif 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"; p.Context.Response.ContentEncoding = System.Text.Encoding.UTF8; ((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 (p.ServerCacheAttributes.Length > 0) { if (p.ServerCacheAttributes[0].IsCacheEnabled) { p.Context.Cache.Add(cacheKey, result, null, DateTime.Now.Add(p.ServerCacheAttributes[0].CacheDuration), System.Web.Caching.Cache.NoSlidingExpiration, System.Web.Caching.CacheItemPriority.Normal, null); if (p.Context.Trace.IsEnabled) { p.Context.Trace.Write(Constant.AjaxID, "Adding result to cache for " + p.ServerCacheAttributes[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.SerializeObject(ex); if (p.Context.Trace.IsEnabled) { p.Context.Trace.Write(Constant.AjaxID, "End ProcessRequest"); } return; } } catch (Exception ex) { p.SerializeObject(ex); if (p.Context.Trace.IsEnabled) { p.Context.Trace.Write(Constant.AjaxID, "End ProcessRequest"); } return; } finally { if (token != IntPtr.Zero) { winctx.Undo(); } } }
/// <summary> /// Runs this instance. /// </summary> 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); // TODO: check why Opera is not working with application/json; // p.Context.Response.AddHeader("Content-Type", "application/json; charset=utf-8"); p.Context.Response.ContentType = p.ContentType; p.Context.Response.ContentEncoding = System.Text.Encoding.UTF8; if(!p.IsValidAjaxToken()) { // TODO: maybe we want to throw a special exception type. p.SerializeObject(new System.Security.SecurityException("The AjaxPro-Token is not valid.")); if(p.Context.Trace.IsEnabled) p.Context.Trace.Write(Constant.AjaxID, "End ProcessRequest"); return; } 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 // Check if we have the same request already in our cache. The // cacheKey will be the type and a hashcode from the parameter values. string cacheKey = p.Type.FullName + "|" + p.GetType().Name + "|" + p.AjaxMethod.Name + "|" + 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.AddHeader("X-" + Constant.AjaxID + "-Cache", "server"); // Return the full output of the last cached call 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.AjaxMethod.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.AjaxMethod.IsStatic) { try { res = p.Type.InvokeMember( p.AjaxMethod.Name, System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.InvokeMethod, 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.AjaxMethod.Invoke(c, po); } } catch(Exception ex) { #if(WEBEVENT) string errorText = string.Format(Constant.AjaxID + " Error", p.Context.User.Identity.Name); #endif if (ex.InnerException != null) { #if(WEBEVENT) Management.WebAjaxErrorEvent ev = new Management.WebAjaxErrorEvent(errorText, p, po, WebEventCodes.WebExtendedBase + 100, ex.InnerException); ev.Raise(); #endif p.SerializeObject(ex.InnerException); } else { #if(WEBEVENT) Management.WebAjaxErrorEvent ev = new Management.WebAjaxErrorEvent(errorText, p, po, WebEventCodes.WebExtendedBase + 101, ex); ev.Raise(); #endif 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"; p.Context.Response.ContentEncoding = System.Text.Encoding.UTF8; ((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(p.ServerCacheAttributes.Length > 0) { if (p.ServerCacheAttributes[0].IsCacheEnabled) { p.Context.Cache.Add(cacheKey, result, null, DateTime.Now.Add(p.ServerCacheAttributes[0].CacheDuration), System.Web.Caching.Cache.NoSlidingExpiration, System.Web.Caching.CacheItemPriority.Normal, null); if (p.Context.Trace.IsEnabled) p.Context.Trace.Write(Constant.AjaxID, "Adding result to cache for " + p.ServerCacheAttributes[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.SerializeObject(ex); if(p.Context.Trace.IsEnabled) p.Context.Trace.Write(Constant.AjaxID, "End ProcessRequest"); return; } } catch(Exception ex) { p.SerializeObject(ex); if(p.Context.Trace.IsEnabled) p.Context.Trace.Write(Constant.AjaxID, "End ProcessRequest"); return; } finally { if(token != IntPtr.Zero) winctx.Undo(); } }