Глобальная обработка ошибок ASP.NET MVCC#

Место общения программистов C#
Ответить
Anonymous
 Глобальная обработка ошибок ASP.NET MVC

Сообщение Anonymous »

У меня есть собственный атрибут HandleError, который обрабатывает ошибки в конвейере MVC; У меня есть защищенный метод void Application_Error(object sender, EventArgs e) в моем Global.asax, который обрабатывает ошибки вне конвейера.

Я столкнулся со сценарием, о возможности которого я даже не подозревал; При реализации DI существует зависимость для ConnectionString, которая берется из файла конфигурации приложения.

Поскольку строка подключения еще не существовала, при создании контроллера возникает ошибка, обычно это приводит к срабатыванию обработчика Application_Error и отображению правильной страницы ошибки (посредством визуализации частичного представления в виде строки и отправки его в качестве ответа, а в случае сбоя он просто записывает «Неустрашимое исключение». ответ.

За исключением этого случая, я получаю ужасный желтый экран смерти ASP.NET по умолчанию «ошибка выполнения». Сообщает мне:


Ошибка выполнения

Описание: На сервере
произошла ошибка приложения. Текущие пользовательские настройки ошибок для этого приложения не позволяют
раскрыть подробности ошибки приложения. просмотрено.

Подробности: Чтобы сведения об этом конкретном сообщении об ошибке были
доступны для просмотра на локальном сервере, создайте тег
в файле конфигурации «web.config», расположенном в корневом каталоге
текущего веб-приложения. Затем для атрибута «mode» этого тега должно быть установлено значение «RemoteOnly». Чтобы разрешить
просмотр сведений на удаленных компьютерах, установите его. "режим" на
"Выкл".


У меня в 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;
}
}
А это мои пользовательские ошибки:
Как вы можете видеть, они довольно обширны, однако они даже не срабатывают в случае доступа к ConnectionStrings, где ConnectionString не существует; что вызывает недоумение.

Он срабатывает в любом контроллере, содержащем исключение, или в исключениях, находящихся за пределами контроллера, поэтому я не понимаю, почему в этом случае все по-другому.

Подробнее здесь: https://stackoverflow.com/questions/946 ... r-handling
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»