0

For testing purposes, I'd like to see all of the properties and their corresponding values of an HttpApplication object (I'm testing some functionality of an HTTPModule). My first thought was to serialize it to XML, then view that or write it to a file.

The problem is, HttpApplication is not a serializable class, so an exception is thrown when I try to serialize. Are there any other techniques, or is it even possible to get a string representation of a non-serializable object? I'd just like to see all of the same properties I get with Intellisense and their values.

I've seen some articles which mention Reflection, but I haven't found anything that suggests it would work for my scenario.

UPDATE:

After getting a couple responses, it looks like I'll need to use Reflection. Here is the code I'm using:

Dim sProps As New StringBuilder
For Each p As System.Reflection.PropertyInfo In oHttpApp.GetType().GetProperties()
  If p.CanRead Then
    sProps.AppendLine(p.Name & ": " & p.GetValue(oHttpApp, Nothing))
  End If
Next

On my AppendLine statement, an exception is thrown right away:

System.InvalidCastException: Operator '&' is not defined for string "Context: " and type 'HttpContext'. at Microsoft.VisualBasic.CompilerServices.Operators.InvokeObjectUserDefinedOperator(UserDefinedOperator Op, Object[] Arguments) at Microsoft.VisualBasic.CompilerServices.Operators.InvokeUserDefinedOperator(UserDefinedOperator Op, Object[] Arguments) at Microsoft.VisualBasic.CompilerServices.Operators.ConcatenateObject(Object Left, Object Right)

@granadaCoder, you mentioned that I'll need to know how "deep" to go, I'm wondering if this is the problem. In the error above, Context is an complex object so I would need to drill into that and get its individual properties, correct? Do you know how I might be able to do that - or would it be as simple as calling GetProperties again on p inside my loop?

lhan
  • 4,585
  • 11
  • 60
  • 105
  • I would do Dim o as Object = p.GetValue(oHttpApp, Nothing). See what that is, and then try to write it out. You're probably gonna have to nest the call for certain types (aka, check the type of "o" and then call a your routine recursively.....you may have to ignore a few others if calling them causes an excepiton. Aka, your code will probably be very customized. Keep in mind, I"m not a Reflection expert. – granadaCoder Feb 22 '13 at 16:38

2 Answers2

2

Sounds like a good use case for reflection--

How to iterate through each property of a custom vb.net object?

You could iterate over all the object's properties and create your own XML/JSON view of them.

Update--

Here is c# code of how i turn any object to a dictionary (which would work for your use case)

    public static Dictionary<string,string> ToDictionary<T>(this T me, string prefix=null) where T:class
    {
        Dictionary<string, string> res = new Dictionary<string, string>();

        if (me == null) return res;


        var bindingFlags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.GetProperty | BindingFlags.GetField;
        var properties = me.GetType().GetProperties(bindingFlags)
            .Where(i => i.CanRead
            );

        foreach (var i in properties)
        {
            var val = i.GetValue(me, null);
            var str = "";
            if (val != null)
                str = val.ToString();
            res[string.Format("{0}{1}", prefix, i.Name)] = str;
        }
        return res;
    }
Community
  • 1
  • 1
Micah
  • 10,295
  • 13
  • 66
  • 95
  • I'm getting an error now, please see my update for more info. – lhan Feb 22 '13 at 16:13
  • you need to make sure the property is a string-- that means that when you called `p.GetValue` it was a httpcontext. – Micah Feb 22 '13 at 16:35
  • try `p.GetValue(oHttpApp, Nothing).ToString()` – Micah Feb 22 '13 at 16:38
  • Hmm.. now I'm getting an exception that says "Session state is not available in this context" and looking through the stack trace, it looks like `System.Web.HttpApplication.get_Session()` is getting called somewhere inside `GetValue()` - Maybe this just won't work with `HttpApplication` objects. – lhan Feb 22 '13 at 16:51
  • Notice the `BindingFlags` -- that could help exclude things you shouldnt GetValue on – Micah Feb 22 '13 at 17:19
  • Thanks - I think this is going to work, I'll test it out and let you know! – lhan Feb 22 '13 at 17:49
1

Some objects are not meant to be serializable. Take an IDataReader for an example.

You're gonna have to go with reflection. And "pluck off" the properties that are readable.

Here's some get-started code.

  private void ReadSomeProperties( SomeNonSerializableObject myObject ) 
  {

     foreach( PropertyInfo pi in myObject.GetType( ).GetProperties( BindingFlags.Instance | BindingFlags.Public | BindingFlags.GetProperty) ) 
     {
     //pi.Name
     //pi.GetValue( myObject, null )
     //don't forget , some properties may only have "setters", look at PropertyInfo.CanRead
     }

  }

Of course, when the property is a complex object (not a scalar), then you have to figure out how "deep" you want to go digging.

granadaCoder
  • 26,328
  • 10
  • 113
  • 146
  • Thank you! I've updated my post, please let me know if you can see what I'm doing wrong. – lhan Feb 22 '13 at 16:13