构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(13)-系统日志和异常的处理③

上一节我们讲了如何捕获异常和记录日志,这一节我们讲,没有捕获的或者忘记捕获的异常包括404错误等,我们统一处理这个异常。

这一讲是利用 Application_Error 捕获所有异常,全局的异常处理为了减少代码,统一异常处理,Application_Error位于Global.asax里面,

protected void Application_Error(object sender, EventArgs e)

当一个异常在调用堆栈中没有被处理,也没有被框架代码处理时,我们说这个异常未处理,它将被ASP.NET捕获

它将捕获所有 Application 级别的 UnhandleException 和 HttpException(比如:访问的页面不存在等)

总之,在这里处理的话,那么在页面中的所有 try/catch 处理都可以不要了,但是我们为了记录日志,在BLL层还是要try catch

对此未处理错误的处理方法是显示一个页面,列出该未处理异常的详细情况。

我们通过 Application_Error事件把错误写进对应的文件里面或者数据库中。

代码语言:javascript
复制
 /// <summary>
        /// 全局的异常处理
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void Application_Error(object sender, EventArgs e)
        {
            string s = HttpContext.Current.Request.Url.ToString();
            HttpServerUtility server = HttpContext.Current.Server;
            if (server.GetLastError() != null)
            {
                Exception lastError = server.GetLastError();
                // 此处进行异常记录,可以记录到数据库或文本,也可以使用其他日志记录组件。
                ExceptionHander.WriteException(lastError);
                Application["LastError"] = lastError;
                int statusCode = HttpContext.Current.Response.StatusCode;
                string exceptionOperator = "/SysException/Error";
                try
                {
                    if (!String.IsNullOrEmpty(exceptionOperator))
                    {
                        exceptionOperator = new System.Web.UI.Control().ResolveUrl(exceptionOperator);
                        string url = string.Format("{0}?ErrorUrl={1}", exceptionOperator, server.UrlEncode(s));
                        string script = String.Format("<script language='javascript' type='text/javascript'>window.top.location='{0}';</script>", url);
                        Response.Write(script);
                        Response.End();
                    }
                }
                catch { }
            }
        }

嘿嘿,我创造了一个错误 Convert.ToInt16("dddd");下面是错误的显示页面

关于错误页面的制作在控制器SysExceptionController增加

代码语言:javascript
复制
       public ActionResult Error()
        {
        BaseException ex = new BaseException();
        return View(ex);
    }</code></pre></div></div><p>添加BaseException类</p><div class="rno-markdown-code"><div class="rno-markdown-code-toolbar"><div class="rno-markdown-code-toolbar-info"><div class="rno-markdown-code-toolbar-item is-type"><span class="is-m-hidden">代码语言:</span>javascript</div></div><div class="rno-markdown-code-toolbar-opt"><div class="rno-markdown-code-toolbar-copy"><i class="icon-copy"></i><span class="is-m-hidden">复制</span></div></div></div><div class="developer-code-block"><pre class="prism-token token line-numbers language-javascript"><code class="language-javascript" style="margin-left:0"> public class BaseException
{
    #region 变量
    private string exceptionMessage;
    private string exceptionName;
    private string innerExceptionMessage;
    private string innerExceptionName;
    private bool isShow;
    private Exception outermostException;
    private string sourceErrorFile;
    private string sourceErrorRowID;
    private string stackInfo;
    private string targetSite;
    #endregion

    #region 属性
    public string ErrorPageUrl
    {
        get
        {
            return this.GetExceptionUrl();
        }
    }
    public Exception Exception
    {
        get
        {
            return (HttpContext.Current.Session[&#34;Exception&#34;] as Exception);
        }
        private set
        {
            HttpContext.Current.Session[&#34;Exception&#34;] = value;
        }
    }
    public string ExceptionMessage
    {
        get
        {
            return this.exceptionMessage;
        }
        private set
        {
            this.exceptionMessage = value;
        }
    }
    public string ExceptionName
    {
        get
        {
            return this.exceptionName;
        }
        private set
        {
            this.exceptionName = value;
        }
    }
    public string InnerExceptionMessage
    {
        get
        {
            return this.innerExceptionMessage;
        }
        private set
        {
            this.innerExceptionMessage = value;
        }
    }
    public string InnerExceptionName
    {
        get
        {
            return this.innerExceptionName;
        }
        private set
        {
            this.innerExceptionName = value;
        }
    }
    public bool IsShowStackInfo
    {
        get
        {
            return this.isShow;
        }
        private set
        {
            this.isShow = value;
        }
    }
    public string SourceErrorFile
    {
        get
        {
            return this.sourceErrorFile;
        }
        private set
        {
            this.sourceErrorFile = value;
        }
    }
    public string SourceErrorRowID
    {
        get
        {
            return this.sourceErrorRowID;
        }
        private set
        {
            this.sourceErrorRowID = value;
        }
    }
    public string StackInfo
    {
        get
        {
            return this.stackInfo;
        }
        private set
        {
            this.stackInfo = value;
        }
    }
    public string TargetSite
    {
        get
        {
            return this.targetSite;
        }
        private set
        {
            this.targetSite = value;
        }
    }
    #endregion


    public BaseException()
    {
        this.outermostException = null;
        this.exceptionName = null;
        this.exceptionMessage = null;
        this.innerExceptionName = null;
        this.innerExceptionMessage = null;
        this.targetSite = null;
        this.stackInfo = null;
        this.sourceErrorFile = null;
        this.sourceErrorRowID = null;
        this.isShow = false;
        try
        {
            this.Exception = HttpContext.Current.Application[&#34;LastError&#34;] as Exception;
            if (this.Exception != null)
            {
                this.outermostException = this.Exception;
                if ((this.Exception is HttpUnhandledException) &amp;&amp; (this.Exception.InnerException != null))
                {
                    this.Exception = this.Exception.InnerException;
                }
                this.ExceptionName = this.GetExceptionName(this.Exception);
                this.ExceptionMessage = this.GetExceptionMessage(this.Exception);
                if (this.Exception.InnerException != null)
                {
                    this.InnerExceptionName = this.GetExceptionName(this.Exception.InnerException);
                    this.InnerExceptionMessage = this.GetExceptionMessage(this.Exception.InnerException);
                }
                this.TargetSite = this.GetTargetSite(this.Exception);
                this.StackInfo = this.GetStackInfo(this.Exception);
                if ((this.outermostException is HttpUnhandledException) &amp;&amp; (this.outermostException.InnerException != null))
                {
                    this.StackInfo = this.StackInfo + &#34;\r\n&lt;a href=&#39;#&#39; onclick=\&#34;if(document.getElementById(&#39;phidden&#39;).style.display==&#39;none&#39;) document.getElementById(&#39;phidden&#39;).style.display=&#39;block&#39;; else document.getElementById(&#39;phidden&#39;).style.display=&#39;none&#39;; return false;\&#34;&gt;&lt;b&gt;[&#34; + this.outermostException.GetType().ToString() + &#34;]&lt;/b&gt;&lt;/a&gt;\r\n&#34;;
                    this.StackInfo = this.StackInfo + &#34;&lt;pre id=&#39;phidden&#39; style=&#39;display:none;&#39;&gt;&#34; + this.outermostException.StackTrace + &#34;&lt;/pre&gt;&#34;;
                }
                this.SourceErrorFile = this.GetSourceErrorFile();
                this.SourceErrorRowID = this.GetSourceErrorRowID();
                this.IsShowStackInfo = true;
            }
            HttpContext.Current.Session[&#34;LastError&#34;] = null;
        }
        catch (Exception exception)
        {
            this.ExceptionMessage = &#34;异常基页出错&#34; + exception.Message;
        }
    }

    #region 方法
    private string GetExceptionMessage(Exception ex)
    {
        return ex.Message;
    }

    private string GetExceptionMessageForLog()
    {
        StringBuilder builder = new StringBuilder(50);
        builder.AppendFormat(&#34;&lt;ExceptionName&gt;{0}&lt;/ExceptionName&gt;&#34;, this.ExceptionName);
        builder.AppendFormat(&#34;&lt;ExceptionMessage&gt;{0}&lt;/ExceptionMessage&gt;&#34;, this.ExceptionMessage);
        builder.AppendFormat(&#34;&lt;InnerExceptionName&gt;{0}&lt;/InnerExceptionName&gt;&#34;, this.InnerExceptionName);
        builder.AppendFormat(&#34;&lt;InnerExceptionMessage&gt;{0}&lt;/InnerExceptionMessage&gt;&#34;, this.InnerExceptionMessage);
        builder.AppendFormat(&#34;&lt;TargetSite&gt;{0}&lt;/TargetSite&gt;&#34;, this.TargetSite);
        builder.AppendFormat(&#34;&lt;ErrorPageUrl&gt;{0}&lt;/ErrorPageUrl&gt;&#34;, this.ErrorPageUrl);
        builder.AppendFormat(&#34;&lt;SourceErrorFile&gt;{0}&lt;/SourceErrorFile&gt;&#34;, this.SourceErrorFile);
        builder.AppendFormat(&#34;&lt;SourceErrorRowID&gt;{0}&lt;/SourceErrorRowID&gt;&#34;, this.SourceErrorRowID);
        return builder.ToString();
    }

    private string GetExceptionMessageForMail()
    {
        StringBuilder builder = new StringBuilder(50);
        builder.Append(&#34;&lt;ExceptionInfo&gt;&#34;);
        builder.Append(this.GetExceptionMessageForLog());
        builder.AppendFormat(&#34;&lt;StackInfo&gt;&lt;![CDATA[{0}]]&gt;&lt;/StackInfo&gt;&#34;, this.StackInfo);
        builder.Append(&#34;&lt;/ExceptionInfo&gt;&#34;);
        return builder.ToString();
    }

    private string GetExceptionName(Exception ex)
    {
        string str = null;
        if (ex != null)
        {
            str = ex.GetType().FullName;
        }

        return str;
    }

    private string GetExceptionUrl()
    {
        string str = null;
        if (HttpContext.Current.Request[&#34;ErrorUrl&#34;] != null)
        {
            str = HttpContext.Current.Request[&#34;ErrorUrl&#34;].ToString();
        }
        return str;
    }

    private string GetSourceErrorFile()
    {
        string stackInfo = this.StackInfo;
        string[] strArray = new string[0];
        if (stackInfo == null)
        {
            return stackInfo;
        }
        strArray = stackInfo.Split(new string[] { &#34;位置&#34;, &#34;行号&#34; }, StringSplitOptions.RemoveEmptyEntries);
        if (strArray.Length &gt;= 3)
        {
            stackInfo = strArray[1];
            if (stackInfo.LastIndexOf(&#34;:&#34;) == (stackInfo.Length - 1))
            {
                stackInfo = stackInfo.Substring(0, stackInfo.Length - 1);
            }
            return stackInfo;
        }
        return &#34;&#34;;
    }
    private string GetSourceErrorRowID()
    {
        string stackInfo = this.StackInfo;
        string[] strArray = new string[0];
        if (stackInfo == null)
        {
            return stackInfo;
        }
        strArray = stackInfo.Split(new string[] { &#34;行号&#34; }, StringSplitOptions.RemoveEmptyEntries);
        if (strArray.Length &gt;= 2)
        {
            stackInfo = strArray[1].Trim();
            string[] strArray2 = stackInfo.Split(new string[] { &#34;\r\n&#34; }, StringSplitOptions.RemoveEmptyEntries);
            if (strArray2.Length &gt;= 2)
            {
                stackInfo = strArray2[0];
            }
            return stackInfo;
        }
        return &#34;&#34;;
    }
    private string GetStackInfo(Exception ex)
    {
        string str = null;
        if (ex != null)
        {
            str = &#34;&lt;b&gt;[&#34; + ex.GetType().ToString() + &#34;]&lt;/b&gt;\r\n&#34; + ex.StackTrace;
            if (ex.InnerException != null)
            {
                str = this.GetStackInfo(ex.InnerException) + &#34;\r\n&#34; + str;
            }
        }
        return str;
    }
    private string GetTargetSite(Exception ex)
    {
        string str = null;
        if (ex != null)
        {
            ex = this.GetBenmostException(ex);
            MethodBase targetSite = ex.TargetSite;
            if (targetSite != null)
            {
                str = string.Format(&#34;{0}.{1}&#34;, targetSite.DeclaringType, targetSite.Name);
            }
        }
        return str;
    }
    protected Exception GetBenmostException(Exception ex)
    {
        while (true)
        {
            if (ex.InnerException != null)
            {
                ex = ex.InnerException;
            }
            else
            {
                return ex;
            }
        }
    }
    #endregion
}</code></pre></div></div><p>添加Error视图</p><div class="rno-markdown-code"><div class="rno-markdown-code-toolbar"><div class="rno-markdown-code-toolbar-info"><div class="rno-markdown-code-toolbar-item is-type"><span class="is-m-hidden">代码语言:</span>javascript</div></div><div class="rno-markdown-code-toolbar-opt"><div class="rno-markdown-code-toolbar-copy"><i class="icon-copy"></i><span class="is-m-hidden">复制</span></div></div></div><div class="developer-code-block"><pre class="prism-token token line-numbers language-javascript"><code class="language-javascript" style="margin-left:0">@model App.Admin.Controllers.BaseException

@{
ViewBag.Title = "异常处理页面";
Layout = "~/Views/Shared/_Index_Layout.cshtml";
}

<h2>系统错误</h2>
<div style="text-align:center;">
<table width="100%" class="blueTab" border="0" cellspacing="1" cellpadding="1">
<tr>
<td colspan="3">
<table cellspacing="0" cellpadding="0" width="100%" border="0">
<tbody>
<tr>
<td >
&nbsp;错误处理页面</td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr id="youhaotishi" >
<td colspan="2" align="left">
&nbsp;欢迎您光临本网站!网站运行发生错误,请与管理员联系。错误原因可能如下:
<br />
&nbsp;&nbsp;&nbsp;1.非法访问页面.
<br />
&nbsp;&nbsp;&nbsp;2.您输入的数据错误.
<br />
&nbsp;&nbsp;&nbsp;3.您访问的页面不存在.
<br />
&nbsp;&nbsp;&nbsp;4.内容不存在,或已被删除.
<br />
&nbsp;&nbsp;&nbsp;5.系统忙,请稍候再试.
</td>
</tr>
<tbody id="detailInformation" style="display: none;">
<tr>
<td width="20%" class="alignRight" nowrap>
<strong>出错页面:</strong>
</td>
<td class="alignLeft">
@Html.DisplayFor(model => model.ErrorPageUrl) </td>
</tr>
<tr>
<td class="alignRight" nowrap>
<strong>异常名称:</strong>
</td>
<td class="alignLeft">
@Html.DisplayFor(model => model.ExceptionName) </td>
</tr>
<tr>
<td class="alignRight" nowrap>
<strong>异常信息:</strong>
</td>
<td class="alignLeft">
@Html.DisplayFor(model => model.ExceptionMessage) </td>
</tr>
<tr id="trInnerExceptionName" runat="server">
<td class="alignRight" nowrap>
<strong>内部异常名称:</strong>
</td>
<td class="alignLeft">
@Html.DisplayFor(model => model.InnerExceptionName) </td>
</tr>
<tr id="trInnerExceptionMessage" runat="server">
<td class="alignRight" nowrap>
<strong>内部异常信息:</strong>
</td>
<td class="alignLeft">
@Html.DisplayFor(model => model.InnerExceptionMessage)
</td>
</tr>
<tr id="trExceptionMethod" runat="server">
<td class="alignRight" nowrap>
<strong>方法名称:</strong>
</td>
<td class="alignLeft" style="background-color: #ffffcc;">
&nbsp;@Html.DisplayFor(model => model.TargetSite) </td>
</tr>
<tr id="trExceptionSource" runat="server">
<td class="alignRight" nowrap>
<strong>源文件:</strong>
</td>
<td class="alignLeft" style="background-color: #ffffcc;">
@Html.DisplayFor(model => model.SourceErrorFile)
</td>
</tr>
<tr id="trExceptionRowId" runat="server">
<td class="alignRight" nowrap>
<strong>行号:</strong>
</td>
<td class="alignLeft" style="background-color: #ffffcc; color: Red">
&nbsp;@Html.DisplayFor(model => model.SourceErrorRowID) </td>
</tr>
<tr runat="server" id="trStack" visible="false">
<td class="alignRight">
<strong>堆栈跟踪:</strong>
</td>
<td class="alignLeft" style="background-color: #ffffcc;">
<code>
<pre id="litStack"><textarea name="errormsg" cols="80" rows="30" readonly="readonly">@Html.DisplayFor(model => model.StackInfo) </textarea> </pre>
</code>
</td>
</tr>
</tbody>
</table>
<a id="showMessage" href="#" onclick="ShowErrorMessage();return false;">显示详细信息</a>
</div>

<script type="text/javascript">

var isShowMessage = true;

function ShowErrorMessage() {

    var obj = document.getElementById(&#34;showMessage&#34;)
    var detailInformation = document.getElementById(&#34;detailInformation&#34;);
    var youhaotishi = document.getElementById(&#34;youhaotishi&#34;);

    if (isShowMessage) {
        obj.innerText = &#34;隐藏详细信息&#34;;
        isShowMessage = false;
        detailInformation.style.display = &#34;block&#34;;
        youhaotishi.style.display = &#34;none&#34;;
    }
    else {
        obj.innerText = &#34;显示详细信息&#34;;
        isShowMessage = true;
        detailInformation.style.display = &#34;none&#34;;
        youhaotishi.style.display = &#34;block&#34;;
    }

}

</script>