Как мога да обработвам грешки в 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, който ще инжектира клас обвивка за услугата към всеки контролер. Самият клас обвивка съдържа няколко зависимости, които зареждат данни от услугата в своя конструктор. Тези зависимости са конфигурирани да бъдат Singletons, така че това натоварване трябва да се случва само веднъж, а не на заявка.   -  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