Search code examples
c#reflectioncrashw3wp

Using reflection on Request crashes w3wp.exe process


Here is my try to make an object dumper:

using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;

namespace Inspector
{
    public static class Inspector
    {
        public static string Inspect(this object o)
        {
            StringBuilder sb = new StringBuilder();
            InspectObject(o, sb);
            return sb.ToString();
        }

        private static void InspectObject(object o, StringBuilder sb)
        {
            Type objType = o.GetType();
            if (objType == typeof(string))
                sb.Append(o.ToString());
            else
            {
                try
                {
                    IList<PropertyInfo> props = new List<PropertyInfo>(objType.GetProperties());

                    foreach (PropertyInfo prop in props)
                    {
                        object propValue = null;
                        ParameterInfo[] ip = prop.GetIndexParameters();
                        if (ip.Length == 0)
                        {
                            propValue = prop.GetValue(o, null);
                            InspectObject(propValue, sb);
                        }
                        else
                        {

                        }
                    }
                }
                catch (Exception ex)
                {
                    sb.Append(string.Format("Exception: {0}", ex.Message));
                }
            }
        }
    }
}

When I am using it to inspect Request (Request.Inspect()) in HomeController's Index method, w3wp.exe process crashes and try-catch block doesn't do it's job.

What is actually happening? Microsoft says, that only unhandled exceptions crash w3wp.exe, but I am calling Request.Inspect() wrapped into parent try-catch block;


Solution

  • I'm not sure what exact type of Request you use, so I just read the documentation of the HttpRequest class. If that's not what you are using, at least I can give you an idea of what's happening:

    1. the HttpRequest class has a property called RequestContext of type RequestContext, so you call InspectObject for that property
    2. this RequestContext has a property HttpContext of type HttpContextBase, so you call InspectObject for that property
    3. this HttpContextBase has a property called Request of type HttpRequest which is the current request, and - yes - you call InspectObject for that property, starting at 1. again because it's the same instance

    So this recursion never stops and you fill your call stack until you get a StackOverflowException. This kind of exception cannot be handled in your catch block because the stack (and with it the whole process) is corrupted already.


    To solve this you need some kind of recursion detection that tells you if you try to inspect an object that has already been inspected. Then you can stop the recursion at that point.
    Alternativly you can stop the recursion at a certain depth. The specific solution depends on what you need all that information for.