我有一个自定义HandleError
属性,处理MVC管道上的错误;我在我的Global.asax
上有一个protected void Application_Error(object sender, EventArgs e)
方法,它处理来自管道外部的错误。ASP.NET MVC全局错误处理
我遇到了一个我不知道的情景;在实施DI时,connectionString
的依赖关系取自应用程序配置文件。
由于连接字符串尚不存在,所以在创建控制器时会引发错误,这通常会导致Application_Error
处理程序触发,并且呈现适当的错误页面(通过将部分视图呈现为字符串并将其作为“致命异常”。对此,并且如果失败,它只是写入响应
除了在这种情况下,我得到的fugly默认ASP.NET“运行时错误”死亡黄屏告诉我:
运行时错误
说明:在 服务器上发生应用程序错误。此应用程序的当前自定义错误设置阻止 查看应用程序错误的详细信息。
详细信息:若要使此特定错误信息的细节是 可见的本地服务器计算机上,请在位于当前Web应用程序的根目录 的“web.config”配置文件中创建一个 标签。该标签 应该将其“模式”属性设置为“RemoteOnly”。要启用 可以在远程计算机上查看详细信息,请将“模式”设置为 “关闭”。
我没有defaultRedirect
集我customErrors
,也不是原来Off
,因为我不想重定向,而是呈现相同页面的用户是在错误,避免不必要的重定向。
我该如何处理这种情况?甚至为什么它以这种方式行事,而不是像控制器之外的任何其他错误?
我意识到这不太可能经常发生,但我希望能够阻止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" />
正如你可以看到这些是相当广泛的,但是他们甚至不访问ConnectionStrings
的情况下,其中ConnectionString
不存在;这有点令人费解。
它确实在任何控制器中包含的异常或异常不在控制器内,所以我不明白为什么这种情况有什么不同。
我和我的错误处理配置更新。 – bevacqua 2012-02-27 16:24:26
使用PartialView怎么样?你可以看看[全局错误处理在MVC中使用PartialView](http://stackoverflow.com/questions/39594409/global-error-handling-using-partialview-in-mvc)? – 2016-09-20 12:46:07