2013-04-29 17 views
5

W trosce o to, aby zawsze wyświetlać przyjazną stronę błędu użytkownikom odwiedzającym witrynę, na której znajduję się catch-all na stronie Global.asax, większość błędów jest obsługiwana przez filtry, które wydają się być preferowane metoda. W większości przypadków działa to dobrze. Jednak podczas Application_Start zdarzenie Application_Error (co zrozumiałe) nie zostanie wywołane.Jak radzić sobie z błędami w pliku Global.asax Application_Start?

Moje zdarzenie Application_Start zawiera kod inicjalizacyjny zależny od zgłoszenia serwisowego, więc łatwo określić punkt awarii, jeśli usługa jest niedostępna z jakiegokolwiek powodu. Jedynym sposobem, w jaki udało mi się to obejść, jest wykonanie następujących czynności.

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; 
     } 
    } 

Następnie Mam następujący kod w Application_BeginRequest

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

To działa, ale wydaje się to trochę hack. Nie jestem też pewny co do konsekwencji wywołania UnloadAppDomain, lub co by się stało, gdyby pojawiło się wiele żądań. Czy istnieje lepszy sposób na zarządzanie tym?

+0

Czy "GlobalFilters.Filters" zawiera 'HandleError'? Jeśli tak, to łapie wszystkie błędy. – alexn

+0

Nie, usunąłem to. – DJG

+0

Przepraszam, że mówię, ale z pewnością posiadanie twojego wniosku_start zależy od usługi, to jest trochę [IMHO] złego posunięcia? Czy w żaden sposób nie można tego przenieść gdzie indziej? Ponieważ początek aplikacji jest nieco ciężki! Spodziewalibyśmy się również, gdyby to się nie udało, a następnie wyładował, że następne żądanie przychodzenia będzie wtedy albo czekać na ukończenie app_start, a następnie odbierz wątek, albo zadzwonić do innej App_Start, która następnie zawiedzie .. –

Odpowiedz

3

Występują problemy z ładowaniem początkowym w App_Start, ponieważ nie ustawiono HttpContext i niektóre klasy bootstapped go potrzebowały; w każdym razie powinno to działać również dla twojego przypadku:

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; 
      } 
     } 
    } 
} 
Powiązane problemy