Klávesové zkratky na tomto webu - rozšířené Na obsah stránky

Ošetření chybových stavů v ASP.NET MVC

12.50 - 22. prosince 2009 | ASP.NET 2.0

Každá aplikace se může dostat do stavu, kdy není vše, jak má být, a nastane chyba. Tyto stavy bychom neměli ignorovat, ale pečlivě ošetřovat. Jak na to se podíváme v tomto spotu.

ASP.NET obsahuje poměrně sofistikovaný mechanismus na zpracování chyb. Ukazuje celkem podrobné chybové výpisy, které jsou nám vývojářům velice užitečné. Nicméně nejsou užitečné naším uživatelům a ještě mohou leccos prozradit našim útočníkům. Proto by v produkci měly být tyto hlášky zakázané.

Konfigurace

Každá aplikace v produkci by měla mít nastavené pěkné chybové stránky, bez podrobností, co se stalo, ale s informacemi, kam dál uživatel může pokračovat. Popřípadě mu pomoci nalézt to, co hledal. K tomu slouží konfigurační element customErrors, kde můžeme nastavit režim zobrazování a jednotlivé stránky, které se mají zobrazit na určitý chybový kód.

Bohužel, systém je navržen zcela kokotsky a pokud chcete v konfiguraci nastavit pro 404 a 500 jiné stránky, jsou vraceny s kódem 200. Proto využijeme jen následující konfiguraci. Zbylá je celkem k ničemu.

<customErrors mode="RemoteOnly" />

Tím docílíme toho, že všechny requesty, které nejsou z tohoto serveru obdrží pěkné chybové stránky. Dotaz z daného serveru dostane podrobný chybový výpis, což se může hodit.

Zpracování chyb

ASP.NET MVC má v sobě základní mechanismus pro ošetřování chyb. Je jím ActionFilter HandleError, který renderuje pohled Error.aspx, pokud dojde k probublání neošetřené výjimky až do akce řadiče.

[HandleError]
public class MyController : Controller {
}

Procento chyb, takto zachytitelných, jistě není malé, ovšem není 100%. Nemusíme chodit pro příklad daleko a stačí udělat chybku v šabloně pohledu. Hned tu máme nepěknou chybovou stránku.

Takovouto chybu odchytíme až v Global.asax:

protected void Application_Error() {
#if DEBUG
  return;
#endif

  Exception exception = Server.GetLastError();

  Response.Clear();

  RouteData routeData = new RouteData();
  routeData.Values.Add("controller", "Error");

  if (IsPageNotFoundException(exception as HttpException)) {
    routeData.Values.Add("action", "NotFound");
  }
  else {
    routeData.Values.Add("action", "Error");
  }

  Server.ClearError();

  IController errorController = new ErrorController();
  errorController.Execute(new RequestContext(new HttpContextWrapper(Context), routeData));
}

Pokud máme aplikaci v debug modu (typicky u vývojáře) je vhodné nechat chyby probublat až k němu. Pokud jsme ale v releasu musíme chybu zpracovat. Na výpis chybové stránky nám poslouží ErrorController, který má dvě akce: NotFound pro 404 a Error pro 500.

public class ErrorController : Controller {

  [StatusCode(HttpStatusCode.NotFound)]
  public ActionResult NotFound() {
    return View();
  }

  [StatusCode(HttpStatusCode.InternalServerError)]
  public ActionResult Error() {
    return View();
  }
}

Díky způsobu hledání šablon v ASPX View enginu, můžeme na Error využít stejnou Error.aspx ve složce Shared jako pro chyby zachycené už na řadiči.

Neplatná referenční identita

Teď se ještě dostaneme k tomu, proč tu máme zpracování HttpException s kódem 404. Kde se vezme?

Typicky, když máme nějakou detail page, snažíme se pomocí nějakého jedinečného identifikátoru natáhnout zobrazovanou entitu. Pokud žádnou nenajdeme je vhodné vyhodit výjimku a protože jsme na úrovni webové aplikace, měla by to být HttpException s kódem 404, která říká, že hledaná stránka nebyla nalezena.

Její zpracování už máme výše vyřešeno. A to je snad pro dnešek vše. :)

Autor: Aleš Roubíček | Přidej komentář | Delicious | Digg | FriendFeed | Facebook | Linkuj! | Jagg

Komentáře RSS

Zatím bez komentáře. Buď první!

Místo pro tvůj názor

Povinné je jméno a komentář, z e-mailu se rozpoznají Gravatary.
Komentář je formátován pomocí Texy! syntaxu.
Například: **tučný text**, *kurzíva*, "text odkazu":adresa.
Internetové adresy jsou převáděny na odkazy.
Na komentáře se můžete odkazovat pomocí [číslo komentáře].

Nový komentář