7

Is there any good way (other than tediously querying each property) to build a diagnostic dump string for an HttpWebRequest in C#? For simple objects one can get away with using new JObject(theObject), but that doesn't work for HttpWebRequest (and toString is, of course, as useless on HttpWebRequest as it is on any C# object).

Is there any general way to do this for any subset of C# objects (other than using new JObject as I already mentioned)?

Update: I've found that using JsonConvert.SerializeObject (one suggestion in Hans' link) does a decent job of dumping the HttpWebRequest (though it doesn't get the request stream). And I kind of got the System.Net.Tracing stuff to work (though the documentation, as usual for .NET stuff, sucks royally).

Hot Licks
  • 47,103
  • 17
  • 93
  • 151
  • 2
    Review [this question](http://stackoverflow.com/questions/2699466/linqpad-dump-extension-method-i-want-one) for options. – Hans Passant Aug 03 '14 at 22:14
  • Are you aware of .NET Tracing: http://blogs.msdn.com/b/dgorti/archive/2005/09/18/471003.aspx and you can write your own trace listener. – Simon Mourier Aug 04 '14 at 06:39
  • I have tried objectdumper but doesnt work if you want to write dumps of objects for debugging check this question that uses linqpad to do it. http://stackoverflow.com/questions/6032908/is-there-a-library-that-provides-a-formatted-dump-function-like-linqpad if that works let me know – dmportella Aug 05 '14 at 21:34
  • 1
    also have you tried using fiddler to see the requests as they are generated instead? – dmportella Aug 05 '14 at 21:36
  • 1
    As @dmportella suggested - if you really need to dump streams along with request headers - consider integrating FiddlerCore into your code. Note that Request/Response streams are not seekable, so you can't read them twice. With intercepting traffic with Fiddler you can see whole request/response just fine. – Alexei Levenkov Aug 09 '14 at 21:59

5 Answers5

11

This turns out to work pretty well:

string httpWebRequestDump(HttpWebRequest hwr)
{
    return JsonConvert.SerializeObject(hwr,Formatting.Indented);
}

The only problem is that it doesn't dump the associated request stream. I have not found a way to extract that from the request.

Hot Licks
  • 47,103
  • 17
  • 93
  • 151
  • 1
    +1. Note that request/response streams are not seekable, so there is really no way to "preview" them without some redesign of the code. – Alexei Levenkov Aug 09 '14 at 22:00
  • This will be very slow and will cause a reference-loop exception –  Oct 19 '17 at 02:49
  • With namespaces if you want to use it quickly somewhere inside Immediate Window: Newtonsoft.Json.JsonConvert.SerializeObject(something ,Newtonsoft.Json.Formatting.Indented); – user1068352 Feb 21 '18 at 14:24
5

As a quick response I would say override the ToString() function by creating your own variant class where the only difference is the ToString() method; for example:

class HttpWebRequest2 : HttpWebRequest
{
    public HttpWebRequest2(System.Runtime.Serialization.SerializationInfo SerializationInfo, System.Runtime.Serialization.StreamingContext StreamingContext) 
        : base(SerializationInfo, StreamingContext) { }

    public override string ToString()
    {
        // Edit ToString() code here.
        // For example:
        string retval = "[Accept] = " + Accept.ToString() 
        + "\r\n[Address] = " + Address.ToString() 
        + "\r\n[AllowAutoRedirect] = " + AllowAutoRedirect.ToString() 
        + "\r\n[AllowReadStreamBuffering] = " + AllowReadStreamBuffering.ToString() 
        + "\r\n[AllowWriteStreamBuffering] = " + AllowWriteStreamBuffering.ToString() 
        + "\r\n[AuthenticationLevel] = " + AuthenticationLevel.ToString() 
        + "\r\n[AutomaticDecompression] = " + AutomaticDecompression.ToString() 
        + "\r\n[CachePolicy] = " + CachePolicy.ToString() 
        + "\r\n[ClientCertificates] = " + ClientCertificates.ToString() 
        + "\r\n[Connection] = " + Connection.ToString() 
        + "\r\n[ConnectionGroupName] = " + ConnectionGroupName.ToString() 
        + "\r\n[ContentLength] = " + ContentLength.ToString() 
        + "\r\n[ContentType] = " + ContentType.ToString() 
        + "\r\n[ContinueDelegate] = " + ContinueDelegate.ToString() 
        + "\r\n[ContinueTimeout] = " + ContinueTimeout.ToString() 
        + "\r\n[CookieContainer] = " + CookieContainer.ToString() 
        + "\r\n[CreatorInstance] = " + CreatorInstance.ToString() 
        + "\r\n[Credentials] = " + Credentials.ToString() 
        + "\r\n[Date] = " + Date.ToString() 
        + "\r\n[DefaultCachePolicy] = " + DefaultCachePolicy.ToString() 
        + "\r\n[DefaultMaximumErrorResponseLength] = " + DefaultMaximumErrorResponseLength.ToString() 
        + "\r\n[DefaultMaximumResponseHeadersLength] = " + DefaultMaximumResponseHeadersLength.ToString() 
        + "\r\n[Expect] = " + Expect.ToString() 
        + "\r\n[HaveResponse] = " + HaveResponse.ToString() 
        + "\r\n[Headers] = " + Headers.ToString() 
        + "\r\n[Host] = " + Host.ToString() 
        + "\r\n[IfModifiedSince] = " + IfModifiedSince.ToString() 
        + "\r\n[ImpersonationLevel] = " + ImpersonationLevel.ToString() 
        + "\r\n[KeepAlive] = " + KeepAlive.ToString() 
        + "\r\n[MaximumAutomaticRedirections] = " + MaximumAutomaticRedirections.ToString() 
        + "\r\n[MaximumResponseHeadersLength] = " + MaximumResponseHeadersLength.ToString() 
        + "\r\n[MediaType] = " + MediaType.ToString() 
        + "\r\n[Method] = " + Method.ToString() 
        + "\r\n[Pipelined] = " + Pipelined.ToString() 
        + "\r\n[PreAuthenticate] = " + PreAuthenticate.ToString() 
        + "\r\n[ProtocolVersion] = " + ProtocolVersion.ToString() 
        + "\r\n[Proxy] = " + Proxy.ToString() 
        + "\r\n[ReadWriteTimeout] = " + ReadWriteTimeout.ToString() 
        + "\r\n[Referer] = " + Referer.ToString() 
        + "\r\n[RequestUri] = " + RequestUri.ToString() 
        + "\r\n[SendChunked] = " + SendChunked.ToString() 
        + "\r\n[ServerCertificateValidationCallback] = " + ServerCertificateValidationCallback.ToString() 
        + "\r\n[ServicePoint] = " + ServicePoint.ToString() 
        + "\r\n[SupportsCookieContainer] = " + SupportsCookieContainer.ToString() 
        + "\r\n[Timeout] = " + Timeout.ToString() 
        + "\r\n[TransferEncoding] = " + TransferEncoding.ToString() 
        + "\r\n[UnsafeAuthenticatedConnectionSharing] = " + UnsafeAuthenticatedConnectionSharing.ToString() 
        + "\r\n[UseDefaultCredentials] = " + UseDefaultCredentials.ToString() 
        + "\r\n[UserAgent] = " + UserAgent.ToString();
        return retval;

    }
}

For the request stream:

For the request stream how about copying it to a memory stream? Along the lines of:

int count = 0;
do
{
  count = responseStream.Read(buffer, 0, buffer.Length);
  memoryStream.Write(buffer, 0, count);
  Response.BinaryWrite(buffer);
}
while (count != 0);
result = memoryStream.ToArray(); // or ToString() etc. as it takes you fancy/suits your needs :)

this would then allow you to leave the original requeststream alone and use the copy in the memory stream to print/store etc as you need.


Which will return a string with all the values that can have getters in HttpWebRequest:)

All you have to do is use HttpWebRequest2() instead and it should be fine:)

Let me know if that helps, or if you need more info/different way of doing it:)

GMasucci
  • 2,834
  • 22
  • 42
3

I liked GMasucci's answer better than JSON serialization because the serialization did not extract the values of the Headers.

I modified GMasucci's answer to be an extension method and use StringBuilder and AppendFormat so that nulls don't blow it up, so if you up-vote this answer, please up-vote his as well. I commented out what seem to be deprecated properties too:

public static String ToStringReadable(this HttpWebRequest request)
    {
        StringBuilder sb = new StringBuilder();
        sb.AppendFormat("[Accept] = {0}", request.Accept);
        sb.AppendFormat("{0}[Address] = {1}", Environment.NewLine, request.Address);
        sb.AppendFormat("{0}[AllowAutoRedirect] = {1}", Environment.NewLine, request.AllowAutoRedirect);
        //sb.AppendFormat("{0}[AllowReadStreamBuffering] = {1}", Environment.NewLine, request.AllowReadStreamBuffering);
        sb.AppendFormat("{0}[AllowWriteStreamBuffering] = {1}", Environment.NewLine, request.AllowWriteStreamBuffering);
        sb.AppendFormat("{0}[AuthenticationLevel] = {1}", Environment.NewLine, request.AuthenticationLevel);
        sb.AppendFormat("{0}[AutomaticDecompression] = {1}", Environment.NewLine, request.AutomaticDecompression);
        sb.AppendFormat("{0}[CachePolicy] = {1}", Environment.NewLine, request.CachePolicy);
        sb.AppendFormat("{0}[ClientCertificates] = {1}", Environment.NewLine, request.ClientCertificates);
        sb.AppendFormat("{0}[Connection] = {1}", Environment.NewLine, request.Connection);
        sb.AppendFormat("{0}[ConnectionGroupName] = {1}", Environment.NewLine, request.ConnectionGroupName);
        sb.AppendFormat("{0}[ContentLength] = {1}", Environment.NewLine, request.ContentLength);
        sb.AppendFormat("{0}[ContentType] = {1}", Environment.NewLine, request.ContentType);
        sb.AppendFormat("{0}[ContinueDelegate] = {1}", Environment.NewLine, request.ContinueDelegate);
        //sb.AppendFormat("{0}[ContinueTimeout] = {1}", Environment.NewLine, request.ContinueTimeout);
        sb.AppendFormat("{0}[CookieContainer] = {1}", Environment.NewLine, request.CookieContainer);
        //sb.AppendFormat("{0}[CreatorInstance] = {1}", Environment.NewLine, request.CreatorInstance);
        sb.AppendFormat("{0}[Credentials] = {1}", Environment.NewLine, request.Credentials);
        //sb.AppendFormat("{0}[Date] = {1}", Environment.NewLine, request.Date);
        //sb.AppendFormat("{0}[DefaultCachePolicy] = {1}", Environment.NewLine, request.DefaultCachePolicy);
        //sb.AppendFormat("{0}[DefaultMaximumErrorResponseLength] = {1}", Environment.NewLine, request.DefaultMaximumErrorResponseLength);
        //sb.AppendFormat("{0}[DefaultMaximumResponseHeadersLength] = {1}", Environment.NewLine, request.DefaultMaximumResponseHeadersLength);
        sb.AppendFormat("{0}[Expect] = {1}", Environment.NewLine, request.Expect);
        sb.AppendFormat("{0}[HaveResponse] = {1}", Environment.NewLine, request.HaveResponse);
        sb.AppendFormat("{0}[Headers] = {1}", Environment.NewLine, request.Headers);
        //sb.AppendFormat("{0}[Host] = {1}", Environment.NewLine, request.Host);
        sb.AppendFormat("{0}[IfModifiedSince] = {1}", Environment.NewLine, request.IfModifiedSince);
        sb.AppendFormat("{0}[ImpersonationLevel] = {1}", Environment.NewLine, request.ImpersonationLevel);
        sb.AppendFormat("{0}[KeepAlive] = {1}", Environment.NewLine, request.KeepAlive);
        sb.AppendFormat("{0}[MaximumAutomaticRedirections] = {1}", Environment.NewLine, request.MaximumAutomaticRedirections);
        sb.AppendFormat("{0}[MaximumResponseHeadersLength] = {1}", Environment.NewLine, request.MaximumResponseHeadersLength);
        sb.AppendFormat("{0}[MediaType] = {1}", Environment.NewLine, request.MediaType);
        sb.AppendFormat("{0}[Method] = {1}", Environment.NewLine, request.Method);
        sb.AppendFormat("{0}[Pipelined] = {1}", Environment.NewLine, request.Pipelined);
        sb.AppendFormat("{0}[PreAuthenticate] = {1}", Environment.NewLine, request.PreAuthenticate);
        sb.AppendFormat("{0}[ProtocolVersion] = {1}", Environment.NewLine, request.ProtocolVersion);
        sb.AppendFormat("{0}[Proxy] = {1}", Environment.NewLine, request.Proxy);
        sb.AppendFormat("{0}[ReadWriteTimeout] = {1}", Environment.NewLine, request.ReadWriteTimeout);
        sb.AppendFormat("{0}[Referer] = {1}", Environment.NewLine, request.Referer);
        sb.AppendFormat("{0}[RequestUri] = {1}", Environment.NewLine, request.RequestUri);
        sb.AppendFormat("{0}[SendChunked] = {1}", Environment.NewLine, request.SendChunked);
        //sb.AppendFormat("{0}[ServerCertificateValidationCallback] = {1}", Environment.NewLine, request.ServerCertificateValidationCallback);
        sb.AppendFormat("{0}[ServicePoint] = {1}", Environment.NewLine, request.ServicePoint);
        //sb.AppendFormat("{0}[SupportsCookieContainer] = {1}", Environment.NewLine, request.SupportsCookieContainer);
        sb.AppendFormat("{0}[Timeout] = {1}", Environment.NewLine, request.Timeout);
        sb.AppendFormat("{0}[TransferEncoding] = {1}", Environment.NewLine, request.TransferEncoding);
        sb.AppendFormat("{0}[UnsafeAuthenticatedConnectionSharing] = {1}", Environment.NewLine, request.UnsafeAuthenticatedConnectionSharing);
        sb.AppendFormat("{0}[UseDefaultCredentials] = {1}", Environment.NewLine, request.UseDefaultCredentials);
        sb.AppendFormat("{0}[UserAgent] = {1}", Environment.NewLine, request.UserAgent);
        return sb.ToString();
    }
jaybro
  • 1,363
  • 1
  • 12
  • 23
0

I modified GMasucci's and jaybro's answers to use HttpRequest, for cases when it is used instead of HttpWebRequest.

public static String ToStringReadable (HttpRequest request)
    {
        StringBuilder sb = new StringBuilder();
        sb.AppendFormat("{0}[AcceptTypes] = {1}", Environment.NewLine, request.AcceptTypes);
        sb.AppendFormat("{0}[AnonymousID] = {1}", Environment.NewLine, request.AnonymousID);
        sb.AppendFormat("{0}[ApplicationPath] = {1}", Environment.NewLine, request.ApplicationPath);
        sb.AppendFormat("{0}[AppRelativeCurrentExecutionFilePath] = {1}", Environment.NewLine, request.AppRelativeCurrentExecutionFilePath);
        sb.AppendFormat("{0}[Browser] = {1}", Environment.NewLine, request.Browser);
        sb.AppendFormat("{0}[ClientCertificate] = {1}", Environment.NewLine, request.ClientCertificate);
        sb.AppendFormat("{0}[ContentEncoding] = {1}", Environment.NewLine, request.ContentEncoding);
        sb.AppendFormat("{0}[ContentLength] = {1}", Environment.NewLine, request.ContentLength);
        sb.AppendFormat("{0}[ContentType] = {1}", Environment.NewLine, request.ContentType);
        sb.AppendFormat("{0}[Cookies] = {1}", Environment.NewLine, request.Cookies);
        sb.AppendFormat("{0}[CurrentExecutionFilePath] = {1}", Environment.NewLine, request.CurrentExecutionFilePath);
        sb.AppendFormat("{0}[CurrentExecutionFilePathExtension] = {1}", Environment.NewLine, request.CurrentExecutionFilePathExtension);
        sb.AppendFormat("{0}[FilePath] = {1}", Environment.NewLine, request.FilePath);
        sb.AppendFormat("{0}[Files] = {1}", Environment.NewLine, request.Files);
        sb.AppendFormat("{0}[Filter] = {1}", Environment.NewLine, request.Filter);
        sb.AppendFormat("{0}[Form] = {1}", Environment.NewLine, request.Form);
        sb.AppendFormat("{0}[Headers] = {1}", Environment.NewLine, request.Headers);
        sb.AppendFormat("{0}[HttpChannelBinding] = {1}", Environment.NewLine, request.HttpChannelBinding);
        sb.AppendFormat("{0}[HttpMethod] = {1}", Environment.NewLine, request.HttpMethod);
        sb.AppendFormat("{0}[InputStream] = {1}", Environment.NewLine, request.InputStream);
        sb.AppendFormat("{0}[IsAuthenticated] = {1}", Environment.NewLine, request.IsAuthenticated);
        sb.AppendFormat("{0}[IsLocal] = {1}", Environment.NewLine, request.IsLocal);
        sb.AppendFormat("{0}[IsSecureConnection] = {1}", Environment.NewLine, request.IsSecureConnection);
        sb.AppendFormat("{0}[Params] = {1}", Environment.NewLine, request.Params);
        sb.AppendFormat("{0}[Path] = {1}", Environment.NewLine, request.Path);
        sb.AppendFormat("{0}[PathInfo] = {1}", Environment.NewLine, request.PathInfo);
        sb.AppendFormat("{0}[PhysicalApplicationPath] = {1}", Environment.NewLine, request.PhysicalApplicationPath);
        sb.AppendFormat("{0}[PhysicalPath] = {1}", Environment.NewLine, request.PhysicalPath);
        sb.AppendFormat("{0}[QueryString] = {1}", Environment.NewLine, request.QueryString);
        sb.AppendFormat("{0}[RawUrl] = {1}", Environment.NewLine, request.RawUrl);
        sb.AppendFormat("{0}[ReadEntityBodyMode] = {1}", Environment.NewLine, request.ReadEntityBodyMode);
        sb.AppendFormat("{0}[RequestContext] = {1}", Environment.NewLine, request.RequestContext);
        sb.AppendFormat("{0}[RequestType] = {1}", Environment.NewLine, request.RequestType);
        sb.AppendFormat("{0}[ServerVariables] = {1}", Environment.NewLine, request.ServerVariables);
        sb.AppendFormat("{0}[TimedOutToken] = {1}", Environment.NewLine, request.TimedOutToken);
        sb.AppendFormat("{0}[TlsTokenBindingInfo] = {1}", Environment.NewLine, request.TlsTokenBindingInfo);
        sb.AppendFormat("{0}[TotalBytes] = {1}", Environment.NewLine, request.TotalBytes);
        sb.AppendFormat("{0}[Unvalidated] = {1}", Environment.NewLine, request.Unvalidated);
        sb.AppendFormat("{0}[Url] = {1}", Environment.NewLine, request.Url);
        sb.AppendFormat("{0}[UrlReferrer] = {1}", Environment.NewLine, request.UrlReferrer);
        sb.AppendFormat("{0}[UserAgent] = {1}", Environment.NewLine, request.UserAgent);
        sb.AppendFormat("{0}[UserHostAddress] = {1}", Environment.NewLine, request.UserHostAddress);
        sb.AppendFormat("{0}[UserHostName] = {1}", Environment.NewLine, request.UserHostName);
        sb.AppendFormat("{0}[UserLanguages] = {1}", Environment.NewLine, request.UserLanguages);
        return sb.ToString();
    }
dan9418
  • 1
  • 1
  • 1
0

The above solutions are pretty much code, plus you'll have to do a lot of things
to keep that code working in the production environment for a long time.

And there could be many other problems you have to solve
only with the Newtonsoft.Json.Linq.JObject solution:

  • recursion in objects
  • non-serializable objects
  • exceptions
  • depth
  • ...

Plus you always want to log more info like:

  • when the event happened
  • callstack
  • which threead
  • what was in the web session
  • ...

There is the best solution that solves all of this and much more.
Use this Nuget package: Desharp.
It's for the web and also for desktop applications. Very addictive.
See it's Desharp Github documentation. It has many configuration options.

Just call anywhere:

Desharp.Debug.Log(yourRequestInstance);

Plus more:

Desharp.Debug.Log(anyException);
Desharp.Debug.Log(anyCustomValueObject);
Desharp.Debug.Log(anyNonserializableObject);
Desharp.Debug.Log(anyFunc);
Desharp.Debug.Log(anything, Desharp.Level.EMERGENCY); // you can store into different files
Desharp.Debug.Dump(anything); // you can dump into browser floating bar

There are a few web demos:

Try to checkout any of them and what is possible to dump or log on HDD:

  • it can save the log in nice HTML (or in TEXT format, configurable)
  • it's possible to write optionally in background thread (configurable)
  • it has options for max objects depth and max strings length (configurable)
  • it uses loops for iteratable objects and backward reflection for everything else,
    indeed for anything you can find in .NET environment.

I believe it will help.

Tom Flídr
  • 101
  • 5