我遇到一个我不知道的情况是可能的;在实现DI时,对于从应用程序配置文件中获取的connectionString有一个依赖关系.
由于连接字符串不存在,创建控制器时会出现错误,这通常会使Application_Error处理程序触发,并且渲染正确的错误页面(通过将部分视图作为字符串呈现,并将其作为响应发送)这种情况就失败了,它只是在响应中写下“致命的异常”.
除了在这种情况下,我得到了默认的默认ASP.NET“运行时错误”黄屏死亡.告诉我:
Runtime Error
Description: An application error occurred on the
server. The current custom error settings for this application prevent
the details of the application error from being viewed.Details: To enable the details of this specific error message to be
viewable on the local server machine,please create a
tag within a “web.config” configuration file located in the root
directory of the current web application. This tag
should then have its “mode” attribute set to “RemoteOnly”. To enable
the details to be viewable on remote machines,please set “mode” to
“Off”.
我的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的情况下甚至不会触发;这有点令人费解.
它在任何控制器中引发的异常或异常都不在控制器内,所以我不明白为什么这种情况是不同的.