如何在我的ASP.NET应用程序中创建"通用错误"页面,以便它处理在提供该页面时触发的错误?

sha*_*oth 4 .net asp.net iis error-handling

在我的ASP.NET MVC应用程序中,我希望有一个通用的错误页面,它与返回的HTTP 500一起显示.类似于Stack Overflow上的这个页面.

当然我想重用尽可能多的代码,以便页面的样式与我的应用程序中的其他页面的样式相同,所以我希望有一个ASP.NET页面重用母版页,而不是纯HTML文件.但是,如果我这样做,我有一个页面,其中包含一些服务器端可执行代码,用于创建提供给客户端的实际HTML.在Stack Overflow一般错误页面的情况下,代码检查用户是否已注册,检索他的代表等,并将其中的元素插入HTML.

该代码可能会失败,如果发生这种情况,页面就没有正确构造,并且服务器中会抛出异常.

如何正常处理这种情况(为错误页面构建HTML时出错)?什么是典型的方法?

Ari*_*tos 7

我想首先对可能的错误进行分类.

对错误进行分类.

  1. 找不到页面(这是我的日志).
  2. 通过尝试破解它来破坏页面的参数
  3. 错误的用户数据输入错误.
  4. 完全未知的错误 - 我们必须修复的新错误.
  5. 一个非常困难的一般错误 - 没有运行 - 例如,数据库根本没有打开.

我们的目标

现在显示错误页面,但仅限于极少数情况.

因此,当用户使用页面进行操作时,我们会尝试捕获用户的所有错误输入,并告诉他如何继续执行任何错误.

全局错误处理程序

您可以global.asax使用void 捕获所有错误Application_Error(object sender, EventArgs e)

void Application_Error(object sender, EventArgs e) 
{
    try
    {
        Exception LastOneError = Server.GetLastError();

        if (LastOneError != null)
        {
            Debug.Fail("Unhandled error: " + LastOneError.ToString());

            if (!(EventLog.SourceExists(SourceName)))
                EventLog.CreateEventSource(SourceName, LogName);

            EventLog MyLog = new EventLog();
            MyLog.Source = SourceName;
            StringBuilder cReportMe = new StringBuilder();

            cReportMe.Append("[Error come from ip:");
            cReportMe.Append(GetRemoteHostIP());
            cReportMe.Append("] ");
            cReportMe.Append("Last Error:");
            cReportMe.Append(LastOneError.ToString());

            if (LastOneError.ToString().Contains("does not exist."))
            {
                // page not found
                MyLog.WriteEntry(cReportMe.ToString(), EventLogEntryType.Warning, 998);
            }
            else
            {
                MyLog.WriteEntry(cReportMe.ToString(), EventLogEntryType.Error, 999);
            }               
        }
    }
    catch (Exception ex)
    {
        Debug.Fail("Unhandled error: " + GlobalFun.GetErrorMessage(ex));
    }

    string cTheFile = HttpContext.Current.Request.Path;

    // to avoid close loop and stackoverflow
    if(!cTheFile.EndsWith("error.aspx"))
        Server.Transfer("~/error.aspx");
}
Run Code Online (Sandbox Code Playgroud)

这个全局错误句柄有一个主要目标,告诉我什么没有工作,并且在到达此处之前无法处理它,所以我记录它(不是记录它的方式)并很快修复它.当我调试我的代码时,我没有使服务器传输能够快速找到错误.

对于黑客错误案例

在这种情况下,最好现在显示任何错误,但只需通过重定向重新加载页面.如何知道它是否试图入侵该页面?

如果在回发后你得到你知道的参数的CRC/hach​​错误.看看答案/sf/answers/178626731/查看视图状态错误的示例以及如何处理它.

我知道MVC没有viewstate,但是你的代码上可能有其他加密字符串,或者某种安全性,你知道它什么时候坏了.这是一般的想法:

if(IsPostBack && HashErrorOnParametres)
{
  LogIt();
  Responce.Redirect(Request.RawUrl, true);
  return;
}
Run Code Online (Sandbox Code Playgroud)

对于非常困难的一般错误

假设您的数据库根本没有打开,然后所有用户都开始从常规处理程序中看到错误页面.在那里你可能有一个额外的选项来重新启动池,或者在最后5分钟或类似的情况下20个错误后停止页面,并发送电子邮件来运行并修复这个非常困难的错误.

对于其余的软错误

我认为必须使用try/catch在页面内处理所有可能的已知错误,并向用户显示出现错误的消息,如果此错误来自用户,并且当然记录它以查看并修复它.

打破部分页面,也许一部分是抛出错误,其余部分工作正常,如果这不是那么重要,你可以简单地隐藏这部分,并显示其余部分,直到你修复它.例如,如果您只显示有关产品的信息,并且说出一个部件的部分会抛出错误,您可以简单地隐藏此部件并在日志中查看并修复它.

有一段时间我试图处理每页错误,protected override void OnError(EventArgs e)但这对我没有帮助,我将其删除.我处理每个操作的错误,如果它们不重要,我会隐藏它们直到我修复它们.

其余的正常错误显示在用户身上,例如没有输入正确的数据......一条消息,告诉他们要修复的内容.

正如我所说,我的目标是根本不显示错误页面.


Jas*_*ans 1

基本上在你的 web.config 中你需要这样的东西:

<customErrors mode="RemoteOnly" defaultRedirect="~/ErrorPages/Oops.aspx">
</customErrors>
Run Code Online (Sandbox Code Playgroud)

当然,错误页面的路径会与上面的不同。

您可以更一般地了解如何处理特定错误,例如这样的 404:

<customErrors mode="RemoteOnly" defaultRedirect="~/ErrorPages/Oops.aspx">
      <error statusCode="404" redirect="~/ErrorPages/404.aspx" />
</customErrors>
Run Code Online (Sandbox Code Playgroud)

编辑:

根据评论,我得到的信息如下:

当您构建“oops.aspx”页面时,我建议您保持简单;如果可能的话,根本没有执行代码。如果您确实需要执行“oops.aspx”中的代码,则将该代码放入一个try..catch块中并消除异常:

try {
    // Your oops code.
}
catch (Exception e) {
    // Do nothing with the exception.
    // Maybe plonk it in a log file, or System.Diagnostics.Trace.WriteLine(e.Message);
}
Run Code Online (Sandbox Code Playgroud)

关键是您要避免调用“oops.aspx”,因为“oops.aspx”本身会导致异常!递归问题啊嘿。

您不需要在母版页中尝试...catch(除非您愿意),我的观点只是集中在“oops.aspx”页面上。