/// <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();
                }
            }
        }
Beispiel #2
0
        /// <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++)
                {
                    IAjaxProcessor ap = p[i];

                    if (ap.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
                            ap.SerializeObject(new NotSupportedException("This method is either not marked with an AjaxMethod or is not available."));
                            return(null);
                        }

                        AjaxMethodAttribute[] ma = (AjaxMethodAttribute[])ap.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(ap));
                            }
                            else
                            {
                                return(new AjaxAsyncHttpHandlerSession(ap));
                            }

                        case HttpSessionStateRequirement.None:
                            if (!useAsync)
                            {
                                return(new AjaxSyncHttpHandler(ap));
                            }
                            else
                            {
                                return(new AjaxAsyncHttpHandler(ap));
                            }

                        default:
                            if (!useAsync)
                            {
                                return(new AjaxSyncHttpHandlerSession(ap));
                            }
                            else
                            {
                                return(new AjaxAsyncHttpHandlerSession(ap));
                            }
                        }
                    }
                }
                break;
            }

            return(null);
        }