我有一個自定義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