잊지 않겠습니다.

Exception을 mail로 보내야지 될 때가 많아서, Exception handler를 간단하게 제작
가장 Key Point는 HttpContext static Member를 이용해서, web에서 발생된 Error도 같이 표현하고 있다는 것이 가장 좋은 점 같다. 

    /// <summary>HtmlError Object.</summary>
    public class ExceptionToHtmlConverter
    {
        public enum ErrorInfoType
        {
            Exception,
            Context
        };
        private delegate string ErrorRendererDelegate(string headerString, NameValueCollection collection);
        static private Hashtable GetErrorInfo(Exception exception)
        {
            Hashtable errorTable = new Hashtable();
            if(exception == null)
            {
                throw new ArgumentNullException("exception");
            }

            // Populate Error Information Collection
            ArrayList errorInfoArray = new ArrayList();
            while(exception != null)
            {

                // Populate Error Information Collection
                NameValueCollection errorInfo = new NameValueCollection();
                errorInfo.Add("Exception Type", exception.GetType().ToString());
                errorInfo.Add("Message", exception.Message);
                errorInfo.Add("Source", exception.Source);
                errorInfo.Add("TargetSite", exception.TargetSite.ToString());
                errorInfo.Add("StackTrace", exception.StackTrace);

                errorInfoArray.Add(errorInfo);
                exception = exception.InnerException;
            }

            errorTable.Add(ErrorInfoType.Exception, errorInfoArray.ToArray());

            if(HttpContext.Current != null)
            {
                Hashtable info = new Hashtable();

                info.Add("QueryString", HttpContext.Current.Request.QueryString);
                info.Add("Form", HttpContext.Current.Request.Form);
                info.Add("Cookies", HttpContext.Current.Request.Cookies);
                info.Add("Session", HttpContext.Current.Session);
                info.Add("Server Variables", HttpContext.Current.Request.ServerVariables);

                errorTable.Add(ErrorInfoType.Context, info);
            }

            return errorTable;

        }
        /// <summary>Returns HTML an formatted error message.</summary>
        static public string GetHtmlError(Exception Ex)
        {
            if(Ex == null)
            {
                throw new ArgumentNullException("Ex");
            }

            // Error Message Header
            StringBuilder sb = new StringBuilder();
            Hashtable errorTable = GetErrorInfo(Ex);
            ErrorRendererDelegate renderer = CollectionToHtmlTable;

            if(HttpContext.Current != null)
            {
                sb.AppendFormat("<font face=\"Arial\" size=\"4\" color=\"red\">An error occurred at {0}<br><font size=\"3\">&nbsp;&nbsp;&nbsp;&nbsp;{1}</font></font><br><br>", HttpContext.Current.Request.Url.ToString(), Ex.Message);
            }

            // Populate Error Information Collection
            foreach(NameValueCollection errorInfo in errorTable[ErrorInfoType.Exception] as object[])
            {
                // Error Information
                sb.Append(renderer("Error Information", BuildCollection(errorInfo)));
            }

            if(errorTable[ErrorInfoType.Context] != null)
            {
                Hashtable info = errorTable[ErrorInfoType.Context] as Hashtable;

                foreach(DictionaryEntry entry in info)
                {
                    sb.AppendFormat("<BR><BR>\n{0}", renderer(entry.Key as string, BuildCollection(entry.Value as ICollection)));
                }
            }

            return sb.ToString();
        }

        /// <summary>Returns HTML an formatted error message.</summary>
        static public string GetTextError(Exception Ex)
        {
            if(Ex == null)
            {
                throw new ArgumentNullException("Ex");
            }

            // Error Message Header
            StringBuilder sb = new StringBuilder();
            Hashtable errorTable = GetErrorInfo(Ex);
            ErrorRendererDelegate renderer = CollectionToTextTable;

            // Populate Error Information Collection
            foreach(NameValueCollection errorInfo in errorTable[ErrorInfoType.Exception] as object[])
            {
                // Error Information
                sb.Append(renderer("Error Information", BuildCollection(errorInfo)));
            }

            if(errorTable[ErrorInfoType.Context] != null)
            {
                Hashtable info = errorTable[ErrorInfoType.Context] as Hashtable;

                foreach(DictionaryEntry entry in info)
                {
                    sb.AppendFormat("\r\n{0}", renderer(entry.Key as string, BuildCollection(entry.Value as ICollection)));
                }
            }

            return sb.ToString();
        }

        #region Private Methods
        static private string CollectionToHtmlTable(string headerString, NameValueCollection collection)
        {

            // Heading Template
            const string heading = @"
  <tr>
    <td bgcolor=""#666666"" colspan=""2"">
      <font face=""Arial"" color=""white""><b>&nbsp;{0}</b></font>
    </td>
  </tr>
";
            // <TD>...</TD> Template
            const string TD = "<td><font face=\"Arial\" size=\"2\"><!--VALUE--></font></td>";

            StringBuilder sb = new StringBuilder();
            // Table Header
            sb.Append("\n<table width=\"100%\" bgcolor=\"#d1d9e4\" cellspacing=\"1\" cellpadding=\"3\">\n");
            sb.AppendFormat(heading, headerString);

            sb.AppendFormat("  <tr bgcolor=\"#d0d0d0\">\n");
            sb.AppendFormat("    {0}\n", TD.Replace("<!--VALUE-->", "&nbsp;<b>Name</b>"));
            sb.AppendFormat("    {0}\n", TD.Replace("<!--VALUE-->", "&nbsp;<b>Value</b>"));
            sb.Append("  </tr>\n");

            // No Body? -> N/A
            if(collection.Count == 0)
            {
                collection = new NameValueCollection();
                collection.Add("N/A", "");
            }

            // Table Body
            for(int i = 0; i < collection.Count; i++)
            {
                sb.AppendFormat("  <tr valign=\"top\" bgcolor=\"{0}\">\n", (i % 2 == 0) ? "white" : "#f4f4f4");
                sb.AppendFormat("    {0}\n", TD.Replace("<!--VALUE-->", collection.Keys[i]));
                sb.AppendFormat("    {0}\n", TD.Replace("<!--VALUE-->", CleanHtml(collection[i])));
                sb.Append("  </tr>\n");
            }

            // Table Footer
            sb.Append("</table>");

            return sb.ToString();
        }
        static private string CollectionToTextTable(string headerString, NameValueCollection collection)
        {

            // Heading Template
            const string heading = "{0}\r\n\r\n";


            StringBuilder sb = new StringBuilder();
            sb.AppendFormat(heading, headerString);


            // No Body? -> N/A
            if(collection.Count == 0)
            {
                collection = new NameValueCollection();
                collection.Add("N/A", "");
            }

            // Table Body
            for(int i = 0; i < collection.Count; i++)
            {
                sb.AppendFormat(" {0} : {1}\r\n", collection.Keys[i], collection[i]);
            }

            return sb.ToString();
        }
        
        static private NameValueCollection BuildCollection(ICollection collection)
        {
            // Overload for HttpCookieCollection collection.
            // Converts HttpCookieCollection to NameValueCollection
            if(collection == null)
            {
                collection = new NameValueCollection();
            }
            NameValueCollection nvCollection = new NameValueCollection();
            IEnumerator en = collection.GetEnumerator();

            object entry;
            while(en.MoveNext())
            {
                entry = en.Current;

                if(collection is HttpCookieCollection)
                {
                    nvCollection.Add(entry.ToString(), (collection as HttpCookieCollection)[entry.ToString()].Value);
                }
                    // Min
                    // CANNOT_MAKE_TEST_CONDITION
                else if(collection is HttpSessionState)
                {
                    nvCollection.Add(entry.ToString(), (collection as HttpSessionState)[entry.ToString()].ToString());
                }
                    // END-CANNOT_MAKE_TEST_CONDITION
                else if(collection is NameValueCollection)
                {
                    if(entry != null)
                    {
                        nvCollection.Add(entry.ToString(), (collection as NameValueCollection)[entry.ToString()].ToString());
                    }
                }
                else
                {
                    throw new NotSupportedException(collection.GetType().ToString());
                }
            }
            return nvCollection;
        }


        static private string CleanHtml(string html)
        {
            // Cleans the string for HTML friendly display
            return (html.Length == 0) ? "" : html.Replace("<", "&lt;").Replace("\r\n", "<BR>").Replace("&", "&amp;").Replace(" ", "&nbsp;");
        }
        #endregion
    }

Posted by Y2K
,