【问题标题】:Understanding error handling in ASP .NET (WebForms)了解 ASP .NET (WebForms) 中的错误处理
【发布时间】:2016-05-30 19:35:39
【问题描述】:

我有一个 Web 窗体 (.NET 4.0) Web 应用程序,它构建为:

  • MyApp.Portal(带有页面、WCF AJAX 服务、脚本等的主门户)
  • MyApp.BusinessLayer(类库调用DataAccess获取数据)
  • MyApp.Services(类库包含用于服务器端代码的 WCF 服务器)
  • MyApp.DataAccess (ADO Oracle)

    我正在尝试遵循一些有关错误处理的教程,但到目前为止我得到的结果不一致。

    我的问题是我应该如何处理我的应用程序中的错误?
    我应该将所有方法都包装在 try/catch 中吗?
    我应该只用 try/catch 将业务层中的方法包装起来吗?
    如何使用 WCF Ajax 方法处理 PortalLayer 中发生的错误?

    例如,我在 Global.asax 文件中添加了以下内容:

    void Application_Error(object sender, EventArgs e)
            {
                // Code that runs when an unhandled error occurs
                Exception exc = Server.GetLastError();
    
                if (exc is HttpUnhandledException)
                {
                    if (exc.InnerException != null)
                    {
                        exc = new Exception(exc.InnerException.Message);
                        Server.Transfer(@"\Pages\Error.aspx?handler=Application_Error%20-%20Global.asax", true);
                    }
                }
    
            }
    

    但是大多数时候这并没有被调用。我只是看到错误,屏幕上显示一条错误消息(如美化警报)。
    或者,如果调用此方法,则 exc 不是 HttpUnhandledException,因此传输永远不会发生。

    我也在我的 web.config 中尝试过这个,但我没有看到这有什么作用。 (如果我将其注释掉,我会得到相同的结果)

    <customErrors mode="On" defaultRedirect="Error.aspx?handler=customErrors%20section%20-%20Web.config">
      <error statusCode="404" redirect="ErrorPage.aspx?msg=404&amp;handler=customErrors%20section%20-%20Web.config"/>
    </customErrors>
    

    最终目标是将用户重定向到一个页面(或者可能只是很好地显示错误),同时将其记录到文件中或将错误写入数据库。

  • 【问题讨论】:

    • Application_Error 不会为 404 调用,因为这发生在应用程序运行之前。事实上,如果你仔细想想,那是有道理的。如果它甚至找不到要运行的应用程序,它如何运行处理程序?另外,Web 服务器本身会处理多种 Http 错误,您必须告诉服务器如何处理它们。
    • 你的问题很广泛。没有答案是完美或正确的。是的,您可以在任何地方且仅在您的 UI 层中“不处理”异常,但这从长远来看是有害的。一般有2种异常。执行异常和业务异常。执行异常是在运行时发生的事情。业务异常是,当您做与您的业务相关的事情时,您必须设置条件,比方说,您的订单不能多于产品 - 您会抛出异常。然后你处理每个。为巴士。例外 - 你描述了为什么你不能继续。
    • 例如,对于运行时异常,您只需说“意外错误”,但您会将所有信息记录在事件日志中。我喜欢 UI 以请求-响应的方式与 BLL 对话。 UI 发送请求 - 获取订单 25 的订单保留。BLL 发送响应 - 如果成功!=true,则这里是数据和成功标志和错误消息。这样,所有 UI 都必须做,显示消息或填充数据。它可以拦截其本地 UI 异常。如果你有这种交流方式,你可以随时改变 UI。有多个 UI 客户端等。

    标签: c# asp.net .net error-handling webforms


    【解决方案1】:

    void Application_Error(object sender, EventArgs e) 将在服务器处理页面(请求 .aspx、.ashx 资源)时因主线程中发生的异常而被调用。

    它不会在两种情况下被调用:

    • 您在处理 .aspx 资源时触发了新线程,并且该新线程中将发生异常
    • 在 Web 服务方法、wcf 方法等(即非 .aspx 资源)中
    • 异常是“坏蛋”异常 - 破坏应用程序域的类型 - StackOverflowExceptionOutOfMemoryException

    所以对于 WCF,WebServices 将所有入口点包装在

    中是有意义的
    try {} 
    catch(Exception e) {
      Logger.Log(e);
      throw;
    } 
    

    声明(请注意,如果您有很多,请花时间在更通用的解决方案上)。

    另请注意 - 如果您的错误页面上有错误,您将获得黄屏死机(显然)。所以我更喜欢将静态 html 页面显示为错误页面(出错的可能性最低)。

    在您的错误处理代码中,您并没有清理错误状态,我更喜欢Redirect 而不是Server.Transfer 进行错误处理。最终截图如下:

     var ex = Server.GetLastError();
     Logger.Log(ex);
     Server.ClearError();
     Response.Redirect("/error.aspx");
    

    最后一点 - 无需自己进行错误日志记录(优秀的程序员是懒惰的 - 就“不要重新发明轮子”而言) - 有很多很棒的日志记录模块,例如 Elmah、Microsoft Enterprise Library 或 log4net。

    【讨论】:

    • 我实现了 log4net 并且可以正常工作,但是对于 WCF 服务,如果我出错并抛出消息,我想在自定义错误页面上显示该消息。现在它只是把它扔到屏幕上。 (我没有看到 YSOD)我必须在每个 catch 语句中重定向吗?
    • 对于未处理的 WCF 异常,处理它们的好方法是实现 WCF 全局异常处理程序 - 即实现您自己的 IErrorHandler 并将其作为行为注册到 web.config 中。同样,为 Web API 注册您自己的 System.Web.Http.ExceptionHandling.ExceptionHandler。这样你就不需要将每个方法都包装在 try/catch 中。
    猜你喜欢
    • 2016-06-22
    • 1970-01-01
    • 2011-03-18
    • 2020-10-08
    • 1970-01-01
    • 1970-01-01
    • 2013-10-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多