Click here to Skip to main content
15,031,145 members
Articles / General Programming / Exceptions
Tip/Trick
Posted 30 Mar 2017

Stats

20.2K views
146 downloads
14 bookmarked

A Quick and Dirty Extension Method to Get the Full Exception Details, Including Inner Exceptions

Rate me:
Please Sign up or sign in to vote.
5.00/5 (11 votes)
1 Apr 2017CPOL2 min read
This tip presents an easy way of verbosely converting an exception and its inner exceptions to a string in order to get access to all details.

Introduction

While exception messages are often clear enough, many times the sole error is "An error occurred while updating the entries. See the inner exception for details." - Everyone who's worked with the entity framework probably stumbled upon this one before - See this post on StackOverflow.com, for example.

Background

This code snippet is intended as an easy way of improving the logged details if the logging framework doesn't support a verbose way of logging inner exceptions. Since it is basically boilerplate code which can be used in any .NET project, I decided to put it up here, for further reference to me (and others) - I can't see why everyone should be writing the same piece of code over and over again. Feel free to adapt it to your individual needs.

Mind you, if you have any other way to get the full exception details, you should probably use that way.

Using the Code

The code itself basically consists of a single static class holding an extension method ToFullBlownString. If you're not familiar with extensions methods, read it up here.

C#
public static class ExceptionExtension
        {
            public static string ToFullBlownString(this System.Exception e, int level = int.MaxValue)
            {
                var sb = new StringBuilder();
                var exception = e;
                var counter = 1;
                while (exception != null && counter <= level)
                { 
                  sb.AppendLine($"{counter}-> Level: {counter}");
                  sb.AppendLine($"{counter}-> Message: {exception.Message}");
                  sb.AppendLine($"{counter}-> Source: {exception.Source}");
                  sb.AppendLine($"{counter}-> Target Site: {exception.TargetSite}");
                  sb.AppendLine($"{counter}-> Stack Trace: {exception.StackTrace}");

                  exception = exception.InnerException;
                  counter++;
                }

            return sb.ToString();
            }
        }

The exception extension basically does the following:

As long as the exception is not null, and counter is below level:

-- print exception level (level is increased for every inner exception)
-- print exception message
-- print exception source
-- print exception target site
-- print exception stack trace

-- - > exception is set to exception.inner exception
-- - > counter is increased by one
-- - > evaluate start condition As long as the exception is not null, and counter is below level again and start over.

Example Output

I've written a little test program which generates an exception containing an inner exception. I called ToFullBlownString twice, once without specifying the level parameter and once with the level parameter set to "1":

Image 1

The test program (which is also included in the source code download) looks like this:

C#
static void Main(string[] args)
        {
            try
            {
                var exception = new Exception("This is an exception. 
                                Please see inner exception for details", GetInnerException());
                throw exception;
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToFullBlownString());
                Console.WriteLine("\n\n\nand now with level = 1:");
                Console.WriteLine(e.ToFullBlownString(1));
            }

            Console.WriteLine("Press any key to exit");
            Console.ReadKey();
        }

        private static Exception GetInnerException()
        {
            try
            {
                throw new Exception("This is the inner exception. 
                               If this was production code, 
                               you'de be presented with details here.");
            }
            catch (Exception e)
            {
                return e;
            }
        }

Further Considerations

Please bear in mind that exception objects sometimes do contain information not meant for everyone to see, for example connection strings and the like. Be careful of what you put into your logfile or display to the end user.

History

  • March 30th, 2017: Initial release
  • April 1st, 2017: Replaced screenshot, added chapter "Further considerations"

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Marco Bertschi
Software Developer
Switzerland Switzerland
I'm a young Software Engineer. Whilst I may accept a 'status quo' as given, it's my responsibility to improve it as soon as the opportunity arises.
Very familiar with the .Net framework since it has been the underlying foundation for most of my professional work so far. I'm that kind of guy who gets stuff done, while I may also improve the way things work whilst I'm at it. Generally can get along well with most people I meet as a professional.
Fervent volunteer firefigter, captain-ranked air force militia spec officer.
Great friend and generally nice to have me around - For a talk, a beer, or a bonfire (I might as well do all of those things combined). Oh, and I really love music - Rock & country that is, mostly.

Comments and Discussions

 
SuggestionEF System.Data.Entity.Validation.DbEntityValidationException Pin
martinrj303-Apr-17 15:49
Membermartinrj303-Apr-17 15:49 
GeneralRe: EF System.Data.Entity.Validation.DbEntityValidationException Pin
Marco Bertschi3-Apr-17 22:26
professionalMarco Bertschi3-Apr-17 22:26 
GeneralNot very good Pin
SteveTheThread1-Apr-17 12:37
MemberSteveTheThread1-Apr-17 12:37 
GeneralRe: Not very good Pin
Marco Bertschi2-Apr-17 20:45
professionalMarco Bertschi2-Apr-17 20:45 
GeneralMy vote of 5 Pin
BillWoodruff31-Mar-17 17:19
mveBillWoodruff31-Mar-17 17:19 
GeneralRe: My vote of 5 Pin
Marco Bertschi1-Apr-17 6:19
professionalMarco Bertschi1-Apr-17 6:19 
No problem, Bill. Thanks for the 5, though.
GeneralMy vote of 5 Pin
Member 787034531-Mar-17 1:30
professionalMember 787034531-Mar-17 1:30 
GeneralRe: My vote of 5 Pin
Marco Bertschi31-Mar-17 2:44
professionalMarco Bertschi31-Mar-17 2:44 
Questionsuggest you post this as a 'Tip' rather than article Pin
BillWoodruff31-Mar-17 0:07
mveBillWoodruff31-Mar-17 0:07 
AnswerRe: suggest you post this as a 'Tip' rather than article Pin
Marco Bertschi31-Mar-17 2:43
professionalMarco Bertschi31-Mar-17 2:43 
GeneralMy vote of 5 Pin
User 1106097930-Mar-17 6:50
MemberUser 1106097930-Mar-17 6:50 
GeneralRe: My vote of 5 Pin
Marco Bertschi30-Mar-17 11:37
professionalMarco Bertschi30-Mar-17 11:37 
GeneralRe: My vote of 5 Pin
User 110609791-Apr-17 2:36
MemberUser 110609791-Apr-17 2:36 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.