2008-10-13 13 views
5

Próbuję zrozumieć problem obsługi błędów w MVC. Czego szukam to scentralizowany sposób na wychwytywanie błędów, ich rejestrowanie, jeśli to możliwe, rozwiązywanie ich, jeśli podejmują inne działania i ostatecznie pokazują właściwy widok dla użytkownika.Obsługa błędów za pomocą ErrorController zamiast bezpośredniego widoku

Myślę, że mogę użyć do tego filtra [HandleError], ale nie widzę żadnego sposobu na przekierowanie go do kontrolera/działania. Jedyną dostępną opcją jest skierowanie jej bezpośrednio do widoku.

Odpowiedz

4

HandleErrorAttribute dostarczana z MVC jest całkiem podstawowym filtrem IExceptionFilter.

Masz kilka opcji, aby osiągnąć to, co myślę, że chcesz.

Można użyć [HandleError (Type = typeof (MyException), widok = "ErrorView")] na działania kontrolerów/lub zaimplementować własną

HandleErrorAttribute isnt bardzo skomplikowane. Myślę, że MS zaleca kopiowanie tego kodu i modyfikowanie go zgodnie z własnymi wymaganiami.

Przesłonięcie funkcji OnException daje dostęp do wszystkich informacji, które mogą być potrzebne - kontroler, akcja, dane trasy itp. - poprzez ExceptionContext.

Pamiętaj, aby ustawić opcję ExceptionHandled. Następnie możesz ustawić filterContext.Result na nową instancję RedirectToAction, która przekierowuje do Twojego ErrorControllera i akcji - oczywiście możesz ujawnić konkretny kontroler i akcję właściwościami.

+0

Standardowy HandleError nie pozwala mi na kierowanie do kontrolera, jak myślę. Więc nie tego potrzebuję. Myślę, że będę musiał przetoczyć własne. Nie masz tutaj dobrego materiału do odniesienia? –

+0

Yup, http://haacked.com/archive/2008/08/14/aspnetmvc-filters.aspx – CVertex

+1

Jep, zauważyłem linki w twojej odpowiedzi odrobinę za późno: P Dzięki. Tworzę teraz RerouteFilterAttribute. Trochę się teraz zaczęło próbować/popełniać błędy, ale dotrę tam. –

1

Dlaczego nie utworzyć własnego ErrorResult pochodzącego z ActionResult?

0

Co robię (który może lub nie może być dobrą praktyką) jest taka:

W przypadku wystąpienia błędu:

  • Gdybym spodziewał i można go obsługiwać, robię (zalogowaniu ją ELMAH)
  • Gdybym spodziewał i nie może poradzić, loguję się do ELMAH i zwracają ViewResult to jest moja strona błędu
    • Dołącz opis błędu standardowego, a wiadomość link do tego, co ja robił
  • Jeśli mi się nie spodziewać, moja ominięcie onError w mojej klasie kontrolera baza robi poprzednim kroku
  • Wszelkie inne błędy, które nie mogą być obsługiwane są automatycznie rejestrowane przez ELMAH a yellowscreens życzenie

Większość moich ogólnych błędów obsługi jest w klasie bazowej dla wszystkich kontrolerów. Jedynym problemem jest to, że muszę ręcznie ustawić kontroler i wartość akcji w klasie bazowej, aby mógł wygenerować link ActionLink dla przekierowania na stronie błędu.

+0

Wydaje się, że filtry wydają się być sposobem na obsługę błędów zamiast przesłonić onerror. Są ładnie ortogonalne dla kontrolerów. – CVertex

+0

Doceń opinię, ale wolałbym nie umieszczać obsługi błędów w tej samej klasie, co mój kontroler podstawowy. Powoduje to, że moja klasa bazowa staje się mniej przydatna do ponownego użycia, ponieważ logika obsługi błędów zwykle jest inna w przypadku każdej witryny. Aktualnie tworzę filtr RerouteErrorAttribute do wykonania zadania. –

2

Leppi, iIf chcesz wysłać do wyniku akcji, możesz zdefiniować akcję i kontroler, aby przekierować przy błędzie. To dobry przykład, ale osobiście nie lubię używać niestandardowych stron ani kodów http do kodów

Oto przykład i mojego IExtenptionFilter. Mój podstawowy kontroler ma domyślny filtr IExceptionFilter do przetwarzania wszystkich kontrolowanych błędów.

[SuppressMessage("Microsoft.Performance", "CA1813:AvoidUnsealedAttributes", 
    Justification = "This attribute is AllowMultiple = true and users might want to override behavior.")] 
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)] 
public class GenericExceptionHandlerFilter : ActionFilterAttribute, IExceptionFilter 
{ 

    public Type ExceptionType { get; set;} 
    public string RedirectToAction { get; set;} 
    public string RedirectToController { get; set;} 

    protected bool ApplyFilter(ExceptionContext filterContext) 
    { 
     Type lExceptionType = filterContext.Exception.GetType(); 
     return (ExceptionType == null || 
       lExceptionType.Equals(ExceptionType)); 
    } 


    #region IExceptionFilter Members 
    public void OnException(ExceptionContext filterContext) 
    { 

     if (ApplyFilter(filterContext)) 
     { 
      IbfControllerLogger.Log(filterContext.Exception); 

      filterContext.ExceptionHandled = true; 

      #region Calculate Action Controller Error 
      RouteValueDictionary lRoutes = new RouteValueDictionary(new 
       { 
        action = RedirectToAction, 
        controller = String.IsNullOrEmpty(RedirectToController) ? (string)filterContext.RouteData.Values["controller"] : RedirectToController 
       }); 
      UrlReWriterUtils.UrlReWriter(filterContext.Controller.ViewData, lRoutes); 
      #endregion 

      filterContext.Controller.TempData[TempDataName.C_TEMPDATA_EXCEPTIONERROR] = filterContext.Exception; 
      filterContext.Result = new RedirectToRouteResult(lRoutes); 
     } 
    } 
    #endregion