I’d like to trap any unhandled exception thrown in an ASP.NET web service, but nothing I’ve tried has worked so far.
First off, the HttpApplication.Error event doesn’t fire on web services, so that’s out..
The next approach was to implement a soap extension, and add it to web.config with:
<soapExtensionTypes>
<add type="Foo" priority="1" group="0" />
</soapExtensionTypes>
However, this doesn’t work if you call the web method over JSON (which my web site does exclusively)..
My next idea would be to write my own HttpHandler for .asmx, which would hopefully derive from System.Web.Script.Services.ScriptHandlerFactory and do something smart. I haven’t tried this yet.
Is there an approach I’m missing? Thanks!
Mike
UPDATE:
I’ll summarize the possibly solutions here:
1) Upgrade to WCF which makes this whole thing much, much easier.
2) Since you cannot sub-class or override the RestHandler class, you would have to re-implement the whole thing as your own IHttpHandler or use reflection to manually call into its methods. Since the source to RestHandler is public and only about 500 lines long, making your own version might not be a huge amount of work but you’d then be responsible for maintaining it. I’m also unaware of any licensing restrictions involved with this code.
3) You can wrap your methods in try/catch blocks, or perhaps use LAMBDA expressions to make this code a bit cleaner. It would still require you to modify each method in your web service.
As described in Capture all unhandled exceptions automatically with WebService there really is no good solution.
The reason that you cannot capture the HttpApplication.Error etc has to do with how the RestHandler has been implemented by the good folks at Microsoft. Specifically, the RestHandler explicitly catches (handles) the exception and writes out the exception details to the Response:
To make matters worse, there is no clean extension point (that I could find) where you can change/extend the behavior. If you want to go down the path of writing your own IHttpHandler, I believe you will pretty much have to re-implement the RestHandler (or RestHandlerWithSession); regardless Reflector will be your friend.
For those that may choose to modify their WebMethods
If you are using Visual Studio 2008 or later, using Lambda expressions makes things not too bad (although not global/generic solution) in terms or removing duplicated code.
Where Execute can be implemented in a subclass of WebService or as an extension method.
UPDATE: Reflection Evil
As mentioned in my origional answer, you can abuse reflection to get what you want… specifically you can create your own HttpHandler that makes use of the internals of the RestHandler to provide an interception point for capturing exception details. I have include an “unsafe” code example below to get you started.
Personally, I would NOT use this code; but it works.