c# – ASP.NET MVC全局错误处理
|
我有一个自定义HandleError属性来处理MVC管道上的错误;我的Global.asax上有一个受保护的void Application_Error(object sender,EventArgs e)方法,它处理管道外部的错误.
我遇到一个我不知道的情况是可能的;在实现DI时,对于从应用程序配置文件中获取的connectionString有一个依赖关系. 由于连接字符串不存在,创建控制器时会出现错误,这通常会使Application_Error处理程序触发,并且渲染正确的错误页面(通过将部分视图作为字符串呈现,并将其作为响应发送)这种情况就失败了,它只是在响应中写下“致命的异常”. 除了在这种情况下,我得到了默认的默认ASP.NET“运行时错误”黄屏死亡.告诉我:
我的customErrors中没有defaultRedirect设置,也没有关闭,因为我不想重定向,而是在用户所在的页面上呈现错误,避免了不必要的重定向. 我如何处理这样的场景?甚至是什么原因,它的行为方式,而不是像控制器之外的任何其他错误? 我意识到这不太可能经常发生,但我希望能够停止YSOD(部分原因是我想隐藏我使用的技术,但主要是因为它不漂亮,也不是用户友好的) 我甚至尝试为UnhandledExceptions注册一个处理程序,但它也没有启动. AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; 最终产生这个的代码是: return ConfigurationManager.ConnectionStrings [key] .ConnectionString;其中ConnectionStrings [key]为null. 更新 这就是应用程序错误的处理方式: protected void Application_Error(object sender,EventArgs e)
{
this.HandleApplicationError(new ResourceController());
}
public static void HandleApplicationError(this HttpApplication application,BaseController controller)
{
if (application == null)
{
throw new ArgumentNullException("application");
}
if (controller == null)
{
throw new ArgumentNullException("controller");
}
application.Response.Clear();
Exception exception = application.Server.GetLastError();
LogApplicationException(application.Response,exception);
try
{
RenderExceptionViewResponse(application,exception,controller);
}
catch (Exception exceptionRenderingView) // now we're in trouble. let's be as graceful as possible.
{
RenderExceptionTextResponse(application,exceptionRenderingView);
}
finally
{
application.Server.ClearError();
}
}
private static void LogApplicationException(HttpResponse response,Exception exception)
{
if (exception is HttpException)
{
HttpException httpException = (HttpException)exception;
if (httpException.GetHttpCode() == (int)HttpStatusCode.NotFound)
{
_log.Debug(Resources.Error.WebResourceNotFound,httpException);
response.Status = Resources.Constants.NotFound;
return;
}
}
_log.Error(Resources.Error.UnhandledException,exception);
}
private static void RenderExceptionViewResponse(HttpApplication application,Exception exception,BaseController controller)
{
if (!RenderAsJsonResponse(application,Resources.User.UnhandledExceptionJson))
{
ErrorViewModel model = WebUtility.GetErrorViewModel(exception);
string result = controller.RenderViewToString(Resources.Constants.ErrorViewName,model);
application.Response.Write(result);
}
}
private static void RenderExceptionTextResponse(HttpApplication application,Exception exceptionRenderingView)
{
application.Response.Clear();
if (!RenderAsJsonResponse(application,Resources.User.FatalExceptionJson))
{
application.Response.Write(Resources.User.FatalException);
}
_log.Fatal(Resources.Error.FatalException,exceptionRenderingView);
}
private static bool RenderAsJsonResponse(HttpApplication application,string message)
{
if (application.Request.IsAjaxRequest())
{
application.Response.Status = Resources.Constants.HttpSuccess;
application.Response.ContentType = Resources.Constants.JsonContentType;
application.Response.Write(message);
return true;
}
return false;
}
这是我用来装饰我的基本控制器的属性: public class ErrorHandlingAttribute : HandleErrorAttribute
{
public Type LoggerType { get; set; }
public ErrorHandlingAttribute()
: this(typeof(ErrorHandlingAttribute))
{
}
public ErrorHandlingAttribute(Type loggerType)
{
LoggerType = loggerType;
}
public override void OnException(ExceptionContext filterContext)
{
if (filterContext.ExceptionHandled)
{
return;
}
if (filterContext.HttpContext.Request.IsAjaxRequest())
{
OnAjaxException(filterContext);
}
else
{
OnRegularException(filterContext);
}
}
internal protected void OnRegularException(ExceptionContext filterContext)
{
Exception exception = filterContext.Exception;
ILog logger = LogManager.GetLogger(LoggerType);
logger.Error(Resources.Error.UnhandledException,exception);
filterContext.HttpContext.Response.Clear();
ErrorViewModel model = WebUtility.GetErrorViewModel(exception);
filterContext.Result = new ViewResult
{
ViewName = Resources.Constants.ErrorViewName,ViewData = new ViewDataDictionary(model)
};
filterContext.ExceptionHandled = true;
}
internal protected void OnAjaxException(ExceptionContext filterContext)
{
Exception exception = filterContext.Exception;
ILog logger = LogManager.GetLogger(LoggerType);
logger.Error(Resources.Error.UnhandledAjaxException,exception);
filterContext.HttpContext.Response.Clear();
filterContext.HttpContext.Response.Status = Resources.Constants.HttpSuccess;
string errorMessage = WebUtility.GetUserExceptionMessage(exception,true);
filterContext.Result = new ExceptionJsonResult(new[] { errorMessage });
filterContext.ExceptionHandled = true;
}
}
这是我的customErrors: <customErrors mode="On" /> 正如你可以看到这些是相当广泛的,但是在访问ConnectionString不存在的ConnectionStrings的情况下甚至不会触发;这有点令人费解. 它在任何控制器中引发的异常或异常都不在控制器内,所以我不明白为什么这种情况是不同的. 解决方法
Application_Error可能是在ASP.NET WebForms中处理错误的推荐方法.但不是在MVC.
我们收到错误过滤器来处理我们的错误.过滤器的问题是它仅在调用控制器时有效. 404和401错误(未找到和授权)以及数据库连接问题是哪个问题. customErrors是去这里的方式.我不明白为什么重定向应该是一个问题? 我正在通过适当的错误处理博客文章:http://blog.gauffin.org/2011/11/how-to-handle-errors-in-asp-net-mvc/ (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
