【问题标题】:Custom error message in ASP.NET MVC when an Exception has been thrown in HttpModule在 HttpModule 中引发异常时,ASP.NET MVC 中的自定义错误消息
【发布时间】:2011-08-31 00:03:20
【问题描述】:

我正在使用 ASP.NET MVC。我在BaseController 中捕获OnException 上的任何未处理的异常,以正确显示好消息。

但是,我在同一个解决方案中有一个 Http Module 项目。如果用户提出错误请求,模块可能会抛出InvalidOperationException。我正在使用 IIS7 集成模式,并且所有配置都已正确配置。我是 IIS 生命周期和 Http 模块异常的新手。

谷歌搜索只找到了使用 HttpMethod 进行异常处理的方法,这与这种情况不同。

问题是如果模块中抛出了异常,MVC 会执行还是不执行?如果确实如此,为什么它不去OnException?以及如何像在 Action 方法中那样在 MVC 中获取异常?

编辑:根据@nickvane 关于应用程序生命周期的回答,我试图更好地解释这种情况。我认为即使是我创建的任何HttpModule 都可能引发任何异常。我希望这个异常由我在UrlRoutingModule 中的 MVC 处理。我在想一个:

  • HttpModule 的顺序
  • 未处理的异常确实会停止模块并且下一个模块将永远不会运行?
  • 如何处理 MVC Web 应用程序 (UrlRoutingModule) 中的异常,如果只是在 UrlRoutingModule 之前或之后执行的另一个 HttpModule 中抛出。
  • 是否可以通过使用context.AllErrorscontext.Error 来获取另一个模块中引发的异常?但我无法得到错误。

我在这个星球上发现的唯一方法是从抛出异常更改为Server.Transfer(),但是其他不是我的模块呢,它仍然抛出异常,我想捕获它。

想一想:我创建了必须返回 JSON 的 MVC Restful API。我可以使用OnException 正确处理 MVC 应用程序中的任何异常,以便任何未处理的异常都将返回类似 {"Error": "An error message here."} 的内容。现在我有可能抛出错误的 HttpModule。该模块不关心 API 和 JSON,它只是抛出一个异常。然后我尝试在 MVC 中捕获这个异常,以 JSON 格式返回。

【问题讨论】:

    标签: asp.net exception asp.net-mvc-3 iis-7 httpmodule


    【解决方案1】:

    控制器或 httpmodule 的生命周期是非常不同的。 此链接显示了 asp.net 应用程序的生命周期:

    http://msdn.microsoft.com/en-us/library/bb470252.aspx

    虽然它不是专门针对 asp.net mvc,但 mvc 框架插入到这个生命周期并遵循这个管道:

    http://ajaxus.net/wp-content/uploads/2010/01/asp_net_mvc_poster.pdf

    来自http://www.asp.net/mvc/tutorials/understanding-the-asp-net-mvc-execution-process-vb

    对基于 ASP.NET MVC 的 Web 的请求 应用程序首先通过 UrlRoutingModule 对象,它是一个 HTTP 模块。该模块解析 请求并执行路由选择。 UrlRoutingModule 对象选择 第一个匹配的路由对象 当前请求。 (一个路由对象 是一个实现 RouteBase 的类, 并且通常是 路由类。)如果没有匹配的路由,则 UrlRoutingModule 对象什么都不做 并让请求回退到 常规 ASP.NET 或 IIS 请求 加工。

    从选定的 Route 对象中, UrlRoutingModule 对象获取 IRouteHandler 对象是 与 Route 对象相关联。 通常,在 MVC 应用程序中,这 将是一个实例 MvcRouteHandler。 IRouteHandler 实例创建一个 IHttpHandler 对象并将其传递给 IHttpContext 目的。默认情况下,IHttpHandler MVC 的实例是 MvcHandler 目的。然后是 MvcHandler 对象 选择将 最终处理请求。

    HttpModule 插入到应用程序生命周期中,并且可以在控制器被实例化之前或在它被释放之后执行代码,这取决于它在应用程序生命周期中处理哪些事件。所以不能使用控制器的异常处理。

    如果您想正确处理 httpmodule 中的异常,我认为您有 2 个选项:

    1. 当您捕捉到异常时,您可以更改请求的响应。您可以插入错误 div 或用错误消息替换整个响应,或者只记录异常。在这种情况下,请求将遵循管道的其余部分。
    2. 或者您可以抛出异常并在 global.asax Application_Error 方法中处理它。在这种情况下,控制器不会被执行。

    如果 HttpModule 抛出有效异常,那么我会选择选项 2。您可以抛出自己的自定义异常并在 global.asax 中以不同方式处理它,甚至返回 HTTP 响应(400 错误请求)。

    更新

    如果在 HttpModule 中抛出异常,它将被 Application_Error 方法捕获。我尝试了以下有效的代码 sn-p,虽然感觉不对:

    protected void Application_Error()
        {
            var ex = Server.GetLastError(); // get the last exception that was made
            if (ex == null) return; // if there is no exception, just continue
            Response.ClearContent();
            Response.Write("{'error':'" + ex.Message + "'}");
            Response.ContentType = "application/json";
            Response.Flush(); // flush the content to the client
            Response.Close(); // and close the connection so that no other content can be written to the response
            Server.ClearError(); // clear the error so that asp.net does not use the custom error page. If we don't close the response and clear the error, the request will still be handled in the rest of the pipeline.
        }
    

    【讨论】:

    • 嗨,很好的解释,我有更好的理解,阅读我的编辑。似乎我需要将其他模块的异常转移/捕获到 UrlRoutingModule。
    • 抛出的异常在 MVC OnException 或 Application_Error 中都没有被捕获,因为它是在其他 HTTP 模块中抛出的。
    • 哈哈,好的。以前我无法使用Context.AllErrorsContext.ErrorApplication_Error() 中获取异常。 Server.GetLastError() 是正确的方法。 Server.ClearError() 还需要删除 ASP.NET HTML 自定义错误页面。现在它可以正确显示 JSON。谢谢。
    猜你喜欢
    • 1970-01-01
    • 2014-11-26
    • 1970-01-01
    • 2018-12-09
    • 1970-01-01
    • 2011-09-23
    • 1970-01-01
    • 2015-10-05
    • 1970-01-01
    相关资源
    最近更新 更多