在HttpModule中抛出异常时ASP.NET MVC中的自定义错误消息

时间:2011-05-23 09:00:50

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

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

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

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

问题是模块中是否抛出了异常MVC是否会执行?如果这样做,为什么它不会OnException?以及如何在Action方法中获取MVC中的异常?

编辑:根据@nickvane对应用程序生命周期的回答,我尝试更好地解释这种情况。我认为即使我创建的任何HttpModule也可能会抛出任何异常。我希望这个异常由UrlRoutingModule中的MVC处理。我想的是:

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

我在这个星球上找到的唯一方法就是从抛出一个例外变为Server.Transfer()但是如何不是我的其他模块,它仍然抛出一个异常,我想抓住它。

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

1 个答案:

答案 0 :(得分:4)

控制器或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   instance创建一个IHttpHandler   对象并将其传递给IHttpContext   宾语。默认情况下,IHttpHandler   MVC的实例是MvcHandler   宾语。然后是MvcHandler对象   选择将要的控制器   最终处理请求。

HttpModule插入应用程序生命周期,可以在实例化控制器之前或处理完控制器之后执行代码,具体取决于它从应用程序生命周期处理的事件。所以它不能使用控制器的异常处理。

如果你想正确处理httpmodule中的异常,我认为你有两个选择:

  1. 当您捕获异常时,您可以更改请求的响应。您可以插入错误div或用错误消息替换整个响应,或者只记录异常。在这种情况下,请求将遵循管道的其余部分。
  2. 或者您可以抛出异常并在global.asax Application_Error方法中处理它。在这种情况下,控制器将不会被执行。
  3. 如果HttpModule抛出一个有效的异常,那么我会去选项2.您可以抛出自己的自定义异常并在global.asax中以不同方式处理它,甚至返回HTTP响应(400 Bad Request)。

    <强>更新

    如果在HttpModule中抛出异常,它将被Application_Error方法捕获。我尝试使用可行的代码片段,虽然感觉不对:

    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.
        }