Вторник, 30 мая, 2017

Трассировка ошибок в представлениях Razor

комментарии: 0

Инструмент System.Diagnostic.Trace является полезным инструментом для логгирования и отладки, и иногда весьма кстати методы трассировки помогают в представлениях Razor.

Например, когда приложение MVC уже запущено на рабочем сервере, то при возникновении большинства ошибок пользователь перенаправляется на представление Views/Shared/Error.cshtml. Это представление по соображениям безопасности не показывает детали ошибки, и все обычно ограничивается небольшим сообщением "Error occurred while processing request" (Возникла ошибка при обработке запроса).

Если запустить то же самое приложение локально, то на странице появится детальная информация об ошибке. Или же можно перехватить исключение, если запустить приложение в режиме отладки. Но как быть с приложением на рабочем сервере.

Если повторить ошибку на рабочем сервере, можно указать продолжать сайту работать дальше и показать подробную информацию об ошибке. Сделать это можно, добавив элемент customErrors в файл web.config внутри элемента system.web.

<system.web>
  <customErrors mode="Off" defaultRedirect="Error" />
       ….

И теперь, после развертывания приложения, мы получим на рабочем сервере подробную информацию и стек вызовов.

Но есть и другая простая альтернатива, которая не выставляет напоказ детали ошибки всем посетителям сайта – это написать код трассировки прямо в представлении Views/Shared/Error.cshtml, например:

@model System.Web.Mvc.HandleErrorInfo

@{
    ViewBag.Title = "Error";
    var message = String.Format(
           "Error in Controller {0}, Action method {1}. Exception: {2}",
                Model.ControllerName,
                Model.ActionName,
                Model.Exception.Message);
    if (Model.Exception.InnerException != null)
    {
        message += "; Inner exception: " +
                  Model.Exception.InnerException.Message;
    }
    System.Diagnostics.Trace.TraceError(message);
}

<hgroup>
    <h1 class="text-error">Error.</h1>
    <h2 class="text-error">
               An error occurred while processing your request.
    </h2>
</hgroup>

С сожалению такой код не будет выполнять трассировку ошибок, например, если запустить приложение в режиме отладки, то метод TraceError просто проигнорируется.

Для работы трассировки нужно еще указать для компилятора константу TRACE, обычно она устанавливается по умолчанию. Нужно просто проверить это в свойствах проекта, на вкладке Build:

Но проблема вот в чем. Эта настройка хранится в файле .csproj и она действует только на файлы .cs. Для компиляции файлов .cshtml (или .aspx для WebForms) ASP.NET использует другой процесс.

Для включения трассировки в представлениях можно добавить в проект статический вспомогательный класс:

public class TraceHelper
{
   public static void Trace(TraceLevel level, string message)
   {
      switch (level)
      {
         case TraceLevel.Error:
             System.Diagnostics.Trace.TraceError(message);
             break;
         case TraceLevel.Warning:
             System.Diagnostics.Trace.TraceWarning(message);
             break;
         case TraceLevel.Info:
             System.Diagnostics.Trace.TraceInformation(message);
             break;
         case TraceLevel.Verbose:
             System.Diagnostics.Trace.WriteLine(message);
             break;
      }
   }
}

Теперь мы можем заменить в файле Error.html строку

System.Diagnostics.Trace.TraceError(message);

на вызов нового статического метода

WebApplication.Code.TraceHelper.Trace(TraceLevel.Error, message);

Итак, добавление трассировки в представления может быть эффективным способом для выявления проблем в приложениях, функционирующих на рабочих серверах. Выше был приведен пример трассировки с представлением Error.cshtml.

Для более общего отслеживания необработанных ошибок лучше использовать фильтр исключений (exception filter). Для этого нужно создать класс в приложении, который реализует интерфейс IExceptionFilter. Например, как в следующем примере:

public class ErrorLoggerFilter : IExceptionFilter    
    {
        void IExceptionFilter.OnException(ExceptionContext filterContext)
        {
            var message = string.Format(
                "Error processing URL: {0}. Exception: {1}",
                filterContext.HttpContext.Request.Url, 
                filterContext.Exception.Message);
            if (filterContext.Exception.InnerException != null)
            {
                message += "; Inner exception: " +
                        filterContext.Exception.InnerException.Message;
            }
            filterContext.HttpContext.Trace.Write(message);
            System.Diagnostics.Trace.TraceError(message);
        }
    }

Затем нужно зарегистрировать этот фильтр в файле App_Start/FilterConfig.cs:

namespace WebApplication
{
    public class FilterConfig
    {
        public static void RegisterGlobalFilters(
                                       GlobalFilterCollection filters)
        {
            filters.Add(new HandleErrorAttribute());
            filters.Add(new WebApplication.Code.ErrorLoggerFilter());
        }
    }
}

Комментарии

 

Добавить комментарий

Войти через Twitter Войти через Facebook Войти через ВКонтакте Войти через Github Войти через Google Войти через LinkedIn

Copyright © 2013 All Rights Reserved for CodeHint.ru      Powered by Windows Azure