This is one of the rare times I’ve needed to append some data to an Exception. And I really hadn’t used Exception.Data before. So today was interesting. I was tired of this third party API causing me inconsistent results when we call methods (because the API is not very reliable in the first place) so I wanted to log the SOAP request that’s being sent every time as part of any logging/debugging which is very useful when you only have just the .NET exception stack and really are missing the other piece of the puzzle, which is what was the SOAP data that was sent over the HttpRequest when you got the error in the first place.
But if you’re handling exceptions correctly and logging them somewhere you should be able to get enough information from your logging to figure out what went wrong in most cases.
Here’s an example of how I used Exception.Data today.
1) I’ve got a Request.cs abstract class
In it, I’ve got the work of setting up and sending the actual HttpRequest via this method:
public Response.Response SendRequest()
{
Stream requestStream;
Stream responseStream;
XmlDocument doc = new XmlDocument();
doc = CreateRequestXML();
// Grab the SOAP that is being sent for possible logging later
_SOAPSent = doc.OuterXml;
// Determines if API call needs to use a session based URI
string requestURI = UseAuthURI == true ? _requestURIAuthBased + SessionID : _requestURI;
byte[] data = XmlUtil.DocumentToBytes(doc);
HttpWebResponse response = null;
// Create the atual Request instance
HttpWebRequest request = CreateWebRequest(requestURI, data.Length);
request.ContentLength = data.Length;
request.KeepAlive = false;
request.Timeout = 30000;
try
{
// Send the Request
requestStream = request.GetRequestStream();
requestStream.Write(data, 0, data.Length);
requestStream.Close();
// get response
response = (HttpWebResponse)request.GetResponse();
}
catch (Exception ex)
{
// include SOAP string that was sent
ex.Data.Add(Enums.ExceptionDataRequest.SOAPCalled, _SOAPSent);
//Throw to retain data
throw;
}
....rest of this returns a response back
}
Notice these lines above:
_SOAPSent = doc.OuterXml;
// include SOAP string that was sent
ex.Data.Add(Enums.ExceptionDataRequest.SOAPCalled, _SOAPSent);
//Throw to retain data
throw;
So I catch the exception and also appending some data to it using Exception.Data. What I added to it was the SOAP text that was sent in the HttpRequest.
Now here’s what you can’t forget to do. You need to re-throw the exception to retain it as I did above or else you’ll lose that data.
2) So now in my code-behind of one of my .aspx I have the following:
private void SomeMethodInCodeBehind()
{
...
try
{
xxx.UpdateFrequency(...);
}
catch (Exception ex)
{
service.LogFailure(..., ex.Data[Enums.ExceptionDataRequest.SOAPCalled].ToString());
}
Response.Redirect("somepage.aspx?freq=1&action=" + _actionID);
}
So here I’m logging the exception and then retrieving that SOAP string that was sent to also log that:
ex.Data[Enums.ExceptionDataRequest.SOAPCalled].ToString()
3) xxx.UpdateFrequency, the method that I called from code-behind looks like this:
public void xxxFrequency(string email, string actionID, string listID)
{
...
UpdateFrequencyRequest request = new UpdateFrequencyRequest(actionID, email, listID);
UpdateFrequencyResponse response = (UpdateFrequencyResponse)request.SendRequest();
...
}
So ultimately this is being wrapped in that try/catch in my code-behind. I make the request and am calling SendRequest(). When the request fails, it will throw that error up the stack until it hits my catch statement in my code-behind in #2. Then I can easily grab the SOAP that was called during that failure.
Now I can log the SOAP anytime I call the request class’s SendRequest easily throughout my code and get something such as this to log and use for debugging if needed:
<Envelope>
<Body>
<SelectRecipient>
<LIST_ID>11111</LIST_ID>
<EMAIL>someemail@domain.com</EMAIL>
</SelectRecipient>
</Body>
</Envelope>
Notice that I also setup an Enum so that I don’t have any magic strings laying around when I’m accessing the keys from the data dictionary.
Pretty cool stuff, common, just never used the data dictionary on the exception object much but definitely powerful.
Print | posted on Thursday, September 10, 2009 8:14 PM