Fouten afhandelen en opsporing in ASP.NET
Door Michiel van Otegem
28 juli 2006
Een applicatie waarin fouten niet goed afgehandeld worden is in eerste instantie
vervelend voor de gebruikers. Daarnaast kan het nare gevolgen hebben voor de server.
Het is dus zaak om fouten netjes af te handelen en om de middelen te hebben fouten
zonodig op te sporen. Hierin kunnen zowel de ontwikkelaar als de systeembeheerder een
rol spelen. De mogelijkheden die ontwikkelaars hebben om de systeembeheerder te helpen
komen in het volgende artikel aan bod.
ASP.NET en het .NET Framework zijn op zich zelf een stuk stabieler dan ASP en applicaties
die direct met Windows communiceren, zoals bijvoorbeeld applicaties geschreven in
Visual Basic 6.0. Het .NET Framework biedt een runtime omgeving die het geheugen voor
applicaties beheert en zorgt dat applicaties niet in elkaars vaarwater terecht komen.
Het voordeel van geheugenbeheer is dat fouten in de programmatuur niet zomaar voor
geheugenlekken kunnen zorgen, omdat er sprake is van garbage collection op het geheugen.
Geheugen dat niet meer nodig is wordt door de garbage collector vrijgegeven. In bijvoorbeeld
ASP en Visual Basic 6 is dat niet zo, dus moet de ontwikkelaar zorgvuldig het gebruikte
geheugen vrijgeven, ook als er fouten optreden. Dat het .NET Framework veel van deze
taken op zich neemt, betekent overigens niet dat de ontwikkelaar zich nergens meer zorgen
over hoeft te maken. Zo is het bijvoorbeeld nog steeds heel belangrijk dat database
verbindingen correct worden afgesloten.
Naast de verbeteringen die de runtime omgeving biedt, zijn in ASP.NET ook de mogelijkheden
om fouten op te sporen en af te handelen veel beter. Foutafhandeling is in ASP.NET
structureel aangepakt, en als zodanig een belangrijk en goed instelbaar onderdeel. De
makkelijkste manier van foutafhandeling is een gebruiker doorverwijzen naar een andere
pagina. Er gebeurt dan weliswaar niet wat de gebruiker wil, maar hij/zij krijgt in
ieder geval geen onbegrijpelijke onzin op het scherm. In Internet Information Server
(IIS) heb je de mogelijkheid om een gebruiker door te verwijzen ook al, maar in ASP.NET
is dit handiger geïmplementeerd. Je kunt de afhandelingspagina's instellen via het
configuratiebestand web.config dat ik in eerdere artikelen al uitgebreid heb besproken.
De afdeling system.web in web.config bevat het element customErrors voor de configuratie
van de foutafhandeling. Het mode attribuut van het customErrors element bepaalt wanneer
een gebruiker wel of niet een nette foutpagina te zien krijgt, en kan drie instellingen
hebben: Off, On, of RemoteOnly. In het eerste geval krijgen gebruikers gewoon de foutmelding
te zien, in het tweede geval krijgen alle gebruikers een nette foutpagina te zien, en
in het derde geval krijgen gebruikers van buitenaf een nette foutpagina te zien, maar
krijgen bezoekers van localhost (dus van de lokale computer) de foutmelding te zien.
Dit is in principe de beste instelling, omdat normale gebruikers dan nooit de fout te
zien krijgen, maar de beheerder wel (iets wat in IIS niet mogelijk is). Het tweede
attribuut van het customErrors element, defaultRedirect, bepaalt welke pagina een
bezoeker te zien krijgt als er een fout optreedt. Als dit attribuut geen waarde heeft
verzorgt ASP.NET zelf een nette foutmelding (zonder verwijzing naar de daadwerkelijke
fout in de code). Het customErrors element kan één of meerdere error elementen bevatten,
die per soort fout een andere pagina kan laten zien. Welke fout een error element
afhandelt, wordt bepaald door de waarde van het statusCode attribuut. Dit attribuut
moet een geldige HTTP status code bevatten. Het redirect attribuut geeft vervolgens
aan welke pagina moet worden weergegeven. Figuur 1 laat een web.config bestand zien
dat instellingen bevat voor foutafhandeling door pagina's waarnaar wordt doorverwezen.
<configuration>
<system.web>
<customErrors
mode="RemoteOnly"
defaultRedirect="error.aspx">
<error
statusCode="404"
redirect="notfound.htm"/>
<error
statusCode="500"
redirect="error500.aspx"/>
</customErrors>
</system.web>
</configuration>
Figuur 1, web.config met instellingen voor foutafhandeling
In Figuur 1 wordt de pagina error500.aspx weergegeven als er een fout optreedt bij het
uitvoeren van een ASP.NET pagina. Dat dit zelf een ASP.NET pagina is, betekent dat je
bijvoorbeeld met de foutpagina de fout kan opslaan in een log (hierover later meer).
Als de gebruiker een pagina opvraagt die niet bestaat, dan wordt notfound.htm weergegeven.
Bij alle andere soorten fouten wordt de gebruiker doorverwezen naar error.aspx. Al deze
instellingen gelden niet voor gebruikers die via localhost pagina's opvragen. Die krijgen
wel eventuele foutmeldingen te zien.
Het handige van web.config is dat je in een submap van de applicatie een web.config kan
zetten die bepaalde instellingen overschrijft voor die map (en de onderliggende mappen).
Zo kun je dus voor verschillende mappen van de applicatie naar verschillende pagina's
verwijzen voor het afhandelen van fouten, en kun je voor bepaalde mappen zelfs de
foutafhandeling uit zetten door mode="Off" te gebruiken. Dit is handig als iemand van
buiten de server komt, maar toch moet kunnen zien wat er fout gaat. Voor die persoon
kun je een beveiligde map maken, waarvoor foutafhandeling uit staat. Wil je nog meer
controle over welke pagina iemand te zien krijgt als er een fout optreedt bij het
compileren of uitvoeren van een pagina, dan kun je ook per pagina nog opgeven naar
welke pagina de gebruiker moet worden doorverwezen. Dit kun je doen met behulp van de
ErrorPage eigenschap van de Page directive, als volgt:
< %@ Page ErrorPage="error500-1.aspx" %>
Door de bovenstaande directive te gebruiken, wordt de gebruiker doorverwezen naar
error500-1.aspx, zelfs als web.config uit figuur 1 actief is.
Debug informatie
Wanneer foutafhandeling uit staat, overal dan wel lokaal, hangt nog van andere instellingen
af wat je te zien krijgt. Zijn er geen andere instellingen gedaan en treedt een fout
op in een pagina, dan krijg je zoiets te zien als in figuur 2.

Figuur 2, Standaardfoutpagina als debugging uit staat
Figuur 2 geeft alleen de foutmelding weer. Overige informatie die je kan helpen bij
het oplossen van de fout (met name de broncode) wordt niet weergegeven vanuit
veiligheidsoverwegingen. Als je meer wil zien dan in figuur 2, dien je voor de pagina
of voor de applicatie debugging aan te zetten. Voor een pagina kun je dit aangeven in
de pagina declaratie, als volgt:
<%@ Page Language="VB" Debug="true" %>
Omdat het erg onhandig is om dit voor alle pagina's aan of uit te moeten zetten, kun
je dit ook instellen in web.config, zoals in figuur 3. De instelling van figuur 3 wordt
gebruikt als er geen instelling in de pagina staat. Je kunt dus per pagina bepalen of
je de standaardinstelling gebruikt of niet. Als debugging aan staat, krijg je in plaats
van figuur 2 zoiets te zien als in figuur 4 (sterker nog, dit is dezelfde pagina als
van figuur 2, maar dan met debugging aan).
<configuration>
<system.web>
<compilation debug="true"/>
</system.web>
</configuration>
Figuur 3, web.config met debugging standaard aan

Figuur 4, Pagina waarvoor debugging aan staat
De instellingen voor debugging hebben alleen betrekking op fouten die optreden tijdens
het uitvoeren van een pagina. Als er een fout optreedt bij het compileren van de pagina,
dan wordt de broncode wel getoond, zoals je kunt zien in figuur 5. Aangezien het vanuit
een beveiligingsoogpunt onverstandig is om broncode mee te sturen, is het dus belangrijk
dat dit normaal gezien alleen voor lokale gebruikers het geval is.

Figuur 5, Compiler fouten worden wel weergegeven
Fouten en problemen opsporen
Een foutmelding hoeft op zich zelf niet altijd genoeg informatie te geven om de fout op
te lossen. Dit geldt helemaal voor zaken die niet echt fout zijn, maar die een bottleneck
vormen bij het serveren van een pagina. Wil je dergelijke problemen kunnen opsporen,
dan moet je kunnen zien wat er gebeurt en in welk volgorde. In ASP kon je dit alleen
doen door zelf een soort trace log te maken, door op strategische punten tekst naar de
browser te schrijven. In ASP.NET is hier een voorziening voor, die je allerhande
informatie geeft over het uitvoeren van de pagina. Hierbij wordt niet alleen informatie
getoond over de volgorde waarin de code wordt uitgevoerd, maar ook informatie die van
belang is voor het uitvoeren van de pagina, zoals informatie over het HTTP request
waarmee de pagina is opgevraagd. Verder kan de ontwikkelaar ook informatie schrijven
naar de trace log. In figuur 6 zie je een gedeelte van de trace informatie die met
een pagina wordt meegestuurd.

Figuur 6, Trace informatie van een pagina
Net als debugging kun je tracing zowel in de pagina als in web.config aan of uit zetten.
In een pagina doe je dat als volgt:
<%@ Page Language="VB" Trace="true" %>
Deze instelling overschrijft de instelling die in web.config staat. In web.config kun
je echter nog meer instellingen doen. De belangrijkste instellingen kun je zien in
figuur 7.
<configuration>
<system.web>
<trace
enabled="true"
pageOutput="false"
requestLimit="15"
localOnly="true"/>
</system.web>
</configuration>
Figuur 7, web.config met trace instellingen
In figuur 7 worden de instellingen voor tracing gedaan via het trace element. Met het
enabled attribuut wordt aangegeven of tracing aan of uit staat. Met het pageOutput
attribuut kun je bepalen of de trace informatie in de pagina getoond moet worden of
niet. Dit lijkt een beetje vreemd, omdat het weinig nut lijkt te hebben om tracing aan
te hebben staan, terwijl het niet in de pagina getoond wordt. De trace informatie wordt
echter ook tijdelijk opgeslagen en is dus later te bekijken. Het aantal requests dat
opgeslagen wordt, kun je aangeven met het requestLimit attribuut. De opgeslagen trace
informatie kun je oproepen via trace.axd in de hoofdmap van de applicatie, dus
bijvoorbeeld via http://www.voorbeeld.nl/trace.axd. Je krijgt dan zoiets te zien als
in figuur 8. Of je trace.axd van buitenaf kunt opvragen, kun je instellen via het
localOnly attribuut. Alleen als dit expliciet op false gezet is, kun je trace.axd vanaf
een andere computer opvragen.

Figuur 8, Trace log
In figuur 8 zie je alle opgeslagen requests. Door op "view details" van een van de
requests te klikken krijg je de trace informatie te zien zoals in figuur 6.
Conclusie
Foutafhandeling en opsporing is in ASP.NET structureel en zeer verfijnd opgezet.
Systeembeheerders kunnen hierdoor makkelijk de foutafhandeling structureel opzetten.
Daar waar nodig kan de systeembeheerder of de ontwikkelaar de instellingen overschrijven
voor een gedeelte van de applicatie of zelfs één pagina. Het volgende artikel zal laten
zien hoe je de bestaande structuur kunt uitbreiden, ten eerste door als ontwikkelaar
trace informatie naar de trace log te schrijven, ten tweede door gebruik te maken van
de Windows Event Log.
Dit artikel is eerder verschenen in Windows & .NET Magazine Benelux, oktober 2002 (huidige naam NetOpus)
|