Throwing better SOAP exceptions

I’m fairly happy with my global unhandled exception handler for WinForms and console apps. I also successfully adapted a version of it for use in ASP.NET apps, where it interfaces with the Application_Error event in global.asax:

Sub Application_Error(ByVal sender As Object, ByVal e As EventArgs)
' Fires when an error occurs
Dim ueh As New AspUnhandledExceptionHandler(True)
ueh.HandleException(Server.GetLastError.GetBaseException())
End Sub

What I haven’t been able to do, however, is get it to work with NET web services. Application_Error never fires for a web service. According to my researchthere really is no good way to generically handle unhandled exception in .NET web services. All the alternatives are... well, bad. Here’s what you can do:

  • Put a try...catch around every WebService method. These methods tend to be wrappers around other classes, so this isn’t quite as bad as it sounds, but it’s still not good.
  • use a Facade design pattern to derive all objects from parent objects that... basically do a try...catch on the .Execute method. Uh, thanks but no thanks.
  • Write a custom SOAP Extension or HttpModule. This sounds reasonable but... hard. If it’s such a cool, important extension or HttpModule, wouldn’t someone have written it already?

Are there any good answers here? I would definitely like feedback if anyone has any suggestions. After some further poking around, I located this Microsoft documentation on Handling and Throwing Exceptions in XML Web Services. While it doesn’t offer any advice on the above, it did illuminate one problem: by default, .NET doesn’t throw very good SOAP Exceptions! You need to re-throw exceptions with some additional data to get the “optional”, but quite helpful, SOAP <detail> error element populated – like so:

Private Sub WebServiceExceptionHandler(ByVal ex As Exception)
Dim ueh As New AspUnhandledExceptionHandler
ueh.HandleException(ex)
'-- Build the detail element of the SOAP fault.
Dim doc As New System.Xml.XmlDocument
Dim node As System.Xml.XmlNode = doc.CreateNode(XmlNodeType.Element, _
SoapException.DetailElementName.Name, _
SoapException.DetailElementName.Namespace)
'-- append our error detail string to the SOAP detail element
Dim details As System.Xml.XmlNode = doc.CreateNode(XmlNodeType.Element, _
"ExceptionInfo", _
SoapException.DetailElementName.Namespace)
details.InnerText = ueh.ExceptionToString(ex)
node.AppendChild(details)
'-- re-throw the exception so we can package additional info
Throw New SoapException("Unhandled Exception: " & ex.Message, _
SoapException.ClientFaultCode, _
Context.Request.Url.ToString, node)
End Sub

And it really does work. This is a capture of a generic exception using a network sniffer, so we’re looking at raw HTTP traffic here.

Before:

HTTP/1.1 500 Internal Server Error.
Date: Wed, 26 May 2004 05:12:08 GMT
Server: Microsoft-IIS/6.0
X-Powered-By: ASP.NET
X-AspNet-Version: 1.1.4322
Cache-Control: private
Content-Type: text/xml; charset=utf-8
Content-Length: 488





soap:Server
Server was unable to process request. --> Object reference not set to an instance of an object.




After:

HTTP/1.1 500 Internal Server Error.
Date: Wed, 26 May 2004 05:09:20 GMT
Server: Microsoft-IIS/6.0
X-Powered-By: ASP.NET
X-AspNet-Version: 1.1.4322
Cache-Control: private
Content-Type: text/xml; charset=utf-8
Content-Length: 782





soap:Server
SoapException
http://192.168.168.10/WebService1/Service1.asmx

System.NullReferenceException
Object reference not set to an instance of an object.
at WebService1.Service1.HelloException2() in HOMESERVERwwwroot$WebService1Service1.asmx.vb:line 70




Notice the <detail> element is fully populated, and the entire <soap:Fault> element is much more informative – cool!

Read more

Stay Gold, America

We are at an unprecedented point in American history, and I'm concerned we may lose sight of the American Dream.

By Jeff Atwood · · Comments

The Great Filter Comes For Us All

With a 13 billion year head start on evolution, why haven't any other forms of life in the universe contacted us by now? (Arrival is a fantastic movie. Watch it, but don't stop there - read the Story of Your Life novella it was based on

By Jeff Atwood · · Comments

I Fight For The Users

If you haven't been able to keep up with my blistering pace of one blog post per year, I don't blame you. There's a lot going on right now. It's a busy time. But let's pause and take a moment

By Jeff Atwood · · Comments

The 2030 Self-Driving Car Bet

It's my honor to announce that John Carmack and I have initiated a friendly bet of $10,000* to the 501(c)(3) charity of the winner’s choice: By January 1st, 2030, completely autonomous self-driving cars meeting SAE J3016 level 5 will be commercially available for passenger

By Jeff Atwood · · Comments