Rick Strahl's Weblog  

Wind, waves, code and everything in between...
.NET • C# • Markdown • WPF • All Things Web
Contact   •   Articles   •   Products   •   Support   •   Advertise
Sponsored by:
Markdown Monster - The Markdown Editor for Windows

.NET Web Services and unhandled Exceptions


:P
On this page:

 

 

I figured out today that .NET WebServices do not fire HttpApplication.Error events on exceptions. This is because WebServices require their own error handlers around the WebService class so that the Exceptions can be wrapped up properly into SoapExceptions and sent back to the client in SOAP formatted messages.

 

Unfortunately this nullifies my generic error handling and logging routines that normally fire in response to exceptions.  My Web apps handle errors through the HttpApplication.Error handler in Global.asax which allows logging and error display. Unfortunately Web Services don’t fire HttpApplication.Error on unhandled exceptions, so this scheme doesn’t work.

 

Ran a quick search on Google trying to figure out whether there is a common error handling handler, but offhand couldn’t find it. The question becomes how do you deal with unhandled Web Service exceptions generically?

 

I’m probably missing some global error handling point, but I needed this done now so my not so clean solution for now is to wrap the entire method into a custom SoapException exception block and use this custom SoapException to log my request. This handler is application specific but can be applied globally – the primary purpose is to log errors.

 

public class LoggingSoapException : SoapException

{

 

      public LoggingSoapException(string ErrorMessage) :

             base(ErrorMessage,SoapException.ServerFaultCode)

      {

                  this.LogException(ErrorMessage,this);

      }

 

      public LoggingSoapException(string ErrorMessage,Exception ex) :

             base(ErrorMessage,SoapException.ServerFaultCode)

      {

            this.LogException(ErrorMessage,ex);

      }

 

      protected void LogException(string ErrorMessage,Exception ex)

      {

            if (ex == null)

                  ex = this;

 

            WebErrorHandler Handler = new WebErrorHandler(ex);

           

            // *** Log the error if specified

            if (App.Configuration.LogErrors == LogType.Xml) 

            {

                  Handler.LogFileName = App.Configuration.XmlErrorLogFile;

                  Handler.LogErrorToXml(true);

                       

            }

            else if (App.Configuration.LogErrors == LogType.SqlServer) 

            {

                  Handler.LogErrorToSql(App.Configuration.ConnectionString);

            }

      }

}

 

Here’s an example of how this can be used:

 

/// <summary>

/// Submits a bug to the server. The bug is forwarded via email and

/// </summary>

/// <param name="NewBug"></param>

/// <returns></returns>

[WebMethod(Description="Submits a bug to be stored to the database and emailed to the configured recipients")]

public int SubmitBug( BugreportsEntity NewBug )

{

      try

      {

            BugReport Bug = new BugReport();

     

            Bug.Pk = 0;

 

            if (!Bug.New() ) 

            {

                  throw new LoggingSoapException(Bug.ErrorMessage);

                  return -1;

            }

 

            // *** Assign our new Pk and update the timestamp to server local time

            NewBug.Pk = Bug.Pk;

            NewBug.Entered = DateTime.Now;

            NewBug.Statusupdate = DateTime.Now;

     

            // *** Move the Incomign proxy data into a new bug

            NewBug.SynchronizeDataRowToProperties( Bug.DataRow );

     

            Bug.SendEmail();

            System.Threading.Thread.Sleep(1000);

 

            if (!Bug.Save())

            {

                  throw new LoggingSoapException(Bug.ErrorMessage);

                  return -1;

            }

 

            return Bug.Pk;

      }

      catch(Exception ex)

      {

            throw new LoggingSoapException(ex.Message,ex);

      }

 

}

 

Unfortunately this approach is not a no touch implementation as you need to wrap methods in an exception block, but it works for the moment. My immediate concern is that I have some odd failures in one of my services and I need to track these down since I haven’t seen these sorts of failures in my dev environment.

 

If anybody knows a more generic mechanism that’d be handy <g>…


The Voices of Reason


 

Mark Pearce
January 30, 2005

# re: .NET Web Services and unhandled Exceptions

Rick, you can create a custom SoapExtension to do this, and then bind it to any web methods where you want to log unhandled exceptions. Useful MSDN articles for this are:
http://tinyurl.com/6gzdg
http://tinyurl.com/6ns48

Or you can read my book [1] which goes into even more gory technical details like how to add a Detail node to the XML exception message to make SoapExceptions more intelligible.

[1] http://sleeksoft.co.uk/public/book/book.html

Mark Pearce
January 30, 2005

# re: .NET Web Services and unhandled Exceptions

And another useful article (from CodeProject):
http://tinyurl.com/582ac

Rick Strahl
January 30, 2005

# re: .NET Web Services and unhandled Exceptions

Thanks Mark, great links! Uggh... that's ugly though both in terms of implementation (SoapExtension and XML Parsing) and setup (adding Extension into Web.Config).

Mark Pearce
February 08, 2005

# re: .NET Web Services and unhandled Exceptions

You're right, it's ugly! I'll post an example on my blog shortly of the same technique, but done in a hopefully more pleasant way.

Shubho
February 05, 2006

# re: .NET Web Services and unhandled Exceptions

If a SoapException is thrown from the WebService method to catch in client side then in that case does the same exceptionalso get caught in the SoapExtension?

XML Web Services
October 05, 2006

# ASP.NET Forums - Soap exceptions


Vitoc
July 18, 2007

# re: .NET Web Services and unhandled Exceptions

I tried using the SoapExtension method, but the problem I'm running into with that is if the web method is invoked on the service with a basic http request that is not using SOAP, if an unhandled exception is thrown in the web service the SoapExtension is not used and you can't get at the exception. Maybe I'm doing something wrong?

I have been unable to find an easy catch-all approach to this, other than making sure to wrap all your web method code in a try/catch block in your webmethods, and while that may be standard practice, it sucks having to rely on the developer and not having a catch-all like you have with web apps using Application_Error in the global.asax.

West Wind  © Rick Strahl, West Wind Technologies, 2005 - 2024