Rion Williams
Rion Williams

Reputation: 76597

Serializing a Request Object using JSON

I'm currently working on a proof-of-concept and ran into an issue involving using JSON to serialize an HttpRequest.

Background

I originally thought that I would be able to easily accomplish it using the JSON.Encode() method as seen below :

JSON.Encode(HttpContext.Request)

However, I quickly found that this causes all sorts of circular references to be thrown (primarily due to the actual structure and complexity of the Request object). These only occur when actually encountering properties that do contain a circular reference, as I have previously used the following code to grab just specific elements that I need :

JSON.Encode(new {HttpContext.Request.Cookies,HttpContext.Request.Headers, ... });

which works just fine.

I'm just curious if there is a better method of handling this (or what the best method of handling it may be). I'll detail a few of the approaches that I have taken so far below to possibly find any areas that I may have gone wrong.

Previous Approaches

My latest approach (using the JSON.NET library) I thought would come close to working, however I encountered an error that involved a "Timeout" property on Stream objects within the Request.

I'm not opposed to simply avoiding serializing Stream objects and Circular References. I'm just trying to grab as much of the Request object as possible while avoiding any of these types of mishaps.

Upvotes: 15

Views: 23281

Answers (3)

Ian G
Ian G

Reputation: 5526

I just attempted to do the same thing, I have now managed to get something serializing using JsonConvert with a contract resolver to ignore all the problem properties - I used this line to do the serialization:

string reqStr = JsonConvert.SerializeObject(context.Request,
    Formatting.Indented, new JsonSerializerSettings {
        ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
        ContractResolver = new IgnoreErrorPropertiesResolver()
});

And here's the contract resolver code I used:

public class IgnoreErrorPropertiesResolver : DefaultContractResolver
{

    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        JsonProperty property = base.CreateProperty(member, memberSerialization);

        if (["InputStream",
            "Filter",
            "Length",
            "Position",
            "ReadTimeout",
            "WriteTimeout",
            "LastActivityDate",
            "LastUpdatedDate",
            "Session"
        ].Contains(property.PropertyName)) {
            property.Ignored = true;
        }
        return property;
    }
}

This will need Newtonsoft.Json.Serialization and System.Reflection usings.

It happens I can't include the Session object where I am, so that's in my list of ignored properties - obviously remove that if you can include it!

Upvotes: 10

Pratima
Pratima

Reputation: 303

I have used JsonConvert.SerializeObject in my project and it is working fine. It seems it may solve your problem.

JsonConvert.SerializeObject(reqObject)

Upvotes: 3

Malcolm O'Hare
Malcolm O'Hare

Reputation: 5009

Any particular reason why you aren't using JSON.Net? It has a setting on it called PreserveReferencesHandling, which tags objects with an additional property ("$id":"##"). If that object appears in the serialization more than once, instead of writing the object again it replaces it with "$ref": "##" pointing to the already existing json for the object. This circumvents circular referencing.

I've never tried returning JSON in that format to an $.ajax call so I don't know what would be involved in parsing it web-side.

Upvotes: 6

Related Questions