Как я могу обрабатывать ошибки в Global.asax Application_Start?

В интересах всегда показывать «дружественную» страницу ошибок пользователям, когда они посещают сайт, у меня есть уловка на странице Global.asax, большинство ошибок обрабатываются фильтрами, которые, по-видимому, являются предпочтительным методом. По большей части это работает нормально. Однако во время Application_Start событие Application_Error (по понятным причинам) не запускается.

Мое событие Application_Start содержит некоторый код инициализации, который зависит от вызова службы, поэтому легко определить точку отказа, если служба недоступна по какой-либо причине. Единственный способ, который я нашел, - это сделать следующее.

    private static Exception StartUpException;
    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        Initialise();       
    }

    private void Initialise()
    {
        StartUpException = null;
        try
        {
            Bootstrapper.Initialise();
        }
        catch (Exception ex)
        {
            StartUpException = ex;
        }
    }

Тогда у меня есть следующий код в Application_BeginRequest

    protected void Application_BeginRequest(object sender, EventArgs e)
    {
        if (StartUpException != null)
        {
            HandleErrorAndRedirect(StartUpException);
            HttpRuntime.UnloadAppDomain();
            Response.End();
        }
    }

Это работает, но похоже на хитрость. Я также не уверен в последствиях вызова UnloadAppDomain или в том, что произойдет, если поступит несколько запросов. Есть ли лучший способ справиться с этим?


person DJG    schedule 29.04.2013    source источник
comment
GlobalFilters.Filters включает HandleError? Если да, то это отлавливает все ошибки.   -  person alexn    schedule 29.04.2013
comment
Нет, я удалил это.   -  person DJG    schedule 29.04.2013
comment
Извините за мои слова, но, конечно, зависимость вашего application_start от службы - это немного [IMHO] плохой ход? Разве это нельзя переместить в другое место? Поскольку запуск приложения немного тяжелый! Я также ожидал, что если он завершится неудачно, а затем выгружается, следующий входящий запрос будет либо ждать завершения app_start, а затем забрать поток, либо вызвать другой App_Start, который затем потерпит неудачу ..   -  person Stuart.Sklinar    schedule 29.04.2013
comment
Возможно, ты прав, но я не уверен, где еще я мог бы это поставить. В коде инициализации я настраиваю контейнер Unity, который будет внедрять класс-оболочку для службы в каждый контроллер. Класс-оболочка сам содержит несколько зависимостей, которые загружают данные из службы в свой конструктор. Эти зависимости настроены как синглтоны, поэтому эта загрузка должна выполняться только один раз, а не для каждого запроса.   -  person DJG    schedule 29.04.2013


Ответы (1)


У нас возникли проблемы с начальной загрузкой в ​​App_Start, потому что HttpContext не был установлен, и некоторым классам с начальной загрузкой он нужен; в любом случае это должно работать и для вашего случая:

public class MvcApplication : System.Web.HttpApplication {    
    protected void Application_BeginRequest() {
        var context = this.Context;
        FirstTimeInitializer.Init(context);
    }

    private static class FirstTimeInitializer {
        private static bool s_IsInitialized = false;
        private static Object s_SyncRoot = new Object();

        public static void Init(HttpContext context) {
            if (s_IsInitialized) {
                return;
            }

            lock (s_SyncRoot) {
                if (s_IsInitialized) {
                    return;
                }

                // bootstrap

                s_IsInitialized = true;
            }
        }
    }
}
person Ondrej Svejdar    schedule 11.06.2013