ExceptionToMessage
        (
            Exception oException
        )
        {
            Debug.Assert(oException != null);
            AssertValid();

            String sMessage = null;

            const String TimeoutMessage =
                "The Twitter Web service didn't respond.";

            const String RefusedMessage =
                "The Twitter Web service refused to provide the requested"
                + " information."
            ;

            if (oException is WebException)
            {
                WebException oWebException = (WebException)oException;

                if (TwitterUtil.WebExceptionIsDueToRateLimit(oWebException))
                {
                    // Note that this shouldn't actually occur, because
                    // this.GetTwitterResponseAsString() pauses and retries when
                    // Twitter rate limits kick in.  This "if" clause is included
                    // in case Twitter misbehaves, or if the pause-retry code is
                    // ever removed from GetTwitterResponseAsString().

                    sMessage = String.Format(

                        RefusedMessage
                        + "  A likely cause is that you have made too many Twitter"
                        + " requests in the last 15 minutes.  (Twitter"
                        + " limits information requests to prevent its service"
                        + " from being attacked.  Click the '{0}' link for"
                        + " details.)"
                        ,
                        TwitterRateLimitsControl.RateLimitingLinkText
                        );
                }
                else if (oWebException.Response is HttpWebResponse)
                {
                    HttpWebResponse oHttpWebResponse =
                        (HttpWebResponse)oWebException.Response;

                    switch (oHttpWebResponse.StatusCode)
                    {
                    case HttpStatusCode.Unauthorized:  // HTTP 401.

                        sMessage = RefusedMessage
                                   + "  The stated reason was \"unauthorized.\"";

                        break;

                    case HttpStatusCode.RequestTimeout:  // HTTP 408.

                        sMessage = TimeoutMessage;
                        break;

                    case HttpStatusCode.Forbidden:  // HTTP 403.

                        sMessage = RefusedMessage
                                   + "  The stated reason was \"forbidden.\"";

                        break;

                    default:

                        break;
                    }
                }
                else
                {
                    switch (oWebException.Status)
                    {
                    case WebExceptionStatus.Timeout:

                        sMessage = TimeoutMessage;
                        break;

                    default:

                        break;
                    }
                }
            }

            if (sMessage == null)
            {
                sMessage = ExceptionUtil.GetMessageTrace(oException);
            }

            return(sMessage);
        }