在ASP.NET MVC中,在我看来,最好的展示未处理的异常是什么?

leo*_*ora 18 c# asp.net-mvc unhandled-exception asp.net-mvc-4 asp.net-mvc-5

我在web.config中有以下内容:

 <customErrors mode="On" defaultRedirect="Error">
  <error statusCode="404" redirect="Error/NotFound" />
</customErrors>
Run Code Online (Sandbox Code Playgroud)

我有一个

 [HandleError]
Run Code Online (Sandbox Code Playgroud)

在我的HomeController类的顶部.为了测试,我创建了一个简单抛出异常的动作..它重定向到我的

 ErrorController/Index
Run Code Online (Sandbox Code Playgroud)

方法,但当它到达我的视图绑定到HandleErrorInfo我的模型为null所以我不知何故失去了对错误的引用.

我确信它与错误在重定向中丢失有关,所以我想看看我是否遗漏了一些东西,如果有人有建议我可以有一个显示Stacktrace和错误消息的视图.

Dav*_*ich 24

我可以看到误解.你想做的MVC事情和redirect控制器动作.

defaultRedirect它本身就是一种Web Form惯例,因而受到限制.当您重定向到另一个控制器时,您将失去您的HttpContext,从而丢失您的HandleErrorInfo对象

您的[HandleError]属性需要a View来指示其错误消息.按照上面的例子,我假设你有一个Views/Error文件夹ErrorController,你有一个Index视图.如果您希望过滤器上下文将HandleErrorInfo对象发送到该视图,

试试这个语法:

[HandleError(View="~/Views/Error/Index")]
Public class HomeController : Controller
Run Code Online (Sandbox Code Playgroud)

但是Logging呢?!?!?

我怀疑你的目的是不仅仅是显示错误堆栈给用户.事实上,我怀疑你根本没有这样的意图.我怀疑你的真正目的是记录你的错误(可能是db)并向你的用户显示一些平淡的消息.

到目前为止我所解释的是" 在我看来,什么是最好的方式来展示未处理的例外 ".该[HandleError]属性对此有利.

但是当您想要进入下一步(记录错误)时,您有以下几种选择:

1)覆盖基本控制器的On Exception方法 ; 创建自己Controller继承自MVC Controller类但是覆盖On Exception方法.此方法可与[HandleError]属性一起使用

2)创建自定义异常处理程序创建自己的异常处理程序,记录错误.然后,您的异常处理程序可以调用View of choice或者可以一起使用,[HandleError(order=2)]因为过滤器属性可以使用优先级的order参数.


Nitin Sawant询问错误视图的样子.该

@model System.Web.Mvc.HandleErrorInfo
<h2>Exception details</h2>
<p> Controller: @Model.ControllerName </p>
<p> Action: @Model.ActionName </p>
<p> Exception: @Model.Exception </p>
Run Code Online (Sandbox Code Playgroud)


Mar*_*rkG 6

我做了类似于maxlego的事情,它处理所有错误(不仅仅是在具有HandleError属性的控制器中发生的错误).

我的MvcApplication类(在global.asax.cs中)有这样的:

public class MvcApplication : HttpApplication
{
    // usual stuff here...

    protected void Application_Error(object sender, EventArgs e)
    {
        Server.HandleError(((MvcApplication)sender).Context);
    }
}
Run Code Online (Sandbox Code Playgroud)

上面的代码使用了我的MVC库中有用的扩展方法.有了这个,我不需要任何错误处理属性,customErrors配置或自定义过滤器.相反,扩展方法将记录错误详细信息,然后调用适当的视图,或者:

  • 拒绝访问
  • 未找到
  • 内部服务器错误

使这项工作的扩展方法代码是:

public static class HttpServerUtilityExtensions
{
    private static readonly Logger Logger = LogManager.GetCurrentClassLogger();

    public static void HandleError(this HttpServerUtility server, HttpContext httpContext)
    {
        var currentController = " ";
        var currentAction = " ";
        var currentRouteData = RouteTable.Routes.GetRouteData(new HttpContextWrapper(httpContext));

        if (currentRouteData != null)
        {
            if (currentRouteData.Values["controller"] != null && !String.IsNullOrEmpty(currentRouteData.Values["controller"].ToString()))
                currentController = currentRouteData.Values["controller"].ToString();

            if (currentRouteData.Values["action"] != null && !String.IsNullOrEmpty(currentRouteData.Values["action"].ToString()))
                currentAction = currentRouteData.Values["action"].ToString();
        }

        var exception = server.GetLastError();
        Logger.ErrorException(exception.Message, exception);

        var controller = DependencyResolver.Current.GetService<ErrorController>();
        var routeData = new RouteData();
        var action = "InternalServerError";

        if (exception is HttpException)
        {
            var httpEx = exception as HttpException;

            switch (httpEx.GetHttpCode())
            {
                case 404:
                    action = "NotFound";
                    break;

                case 401:
                    action = "AccessDenied";
                    break;
            }
        }

        httpContext.ClearError();
        httpContext.Response.Clear();
        httpContext.Response.StatusCode = exception is HttpException ? ((HttpException)exception).GetHttpCode() : 500;
        httpContext.Response.TrySkipIisCustomErrors = true;

        routeData.Values["controller"] = "Error";
        routeData.Values["action"] = action;

        controller.ViewData.Model = new HandleErrorInfo(exception, currentController, currentAction);
        ((IController)controller).Execute(new RequestContext(new HttpContextWrapper(httpContext), routeData));
    }
}
Run Code Online (Sandbox Code Playgroud)

注意,上面使用NLog记录错误详细信息,但可以轻松更改以支持其他内容.此外,此方法在解析ErrorController时会尊重您的IoC容器.