Sinds Windows Vista kunnen ontwikkelaars gebruik maken van een nieuwe webhosting platform, namelijk Internet Information Services (IIS) 7.0. Natuurlijk heeft dat in de praktijk niet zo heel veel zin. Immers, wie gebruikt Vista om webapplicaties op te hosten? Het wachten was op Windows Server 2008 waarin deze versie van IIS eveneens is opgenomen. Microsoft.com en een paar duizend andere sites draaien al Windows Server 2008. In dit artikel kijken we naar de nieuwe mogelijkheden van IIS 7 en vooral wat dat voor ontwikkelaars betekent.
Beheer
Het eerste dat opvalt is de nieuwe beheersinterface. De oude MMC snap-in is vervangen en alhoewel het nog steeds een MMC snap-in lijkt, is het in feite een Windows Forms applicatie.

Figuur 1: Internet Information Services (IIS) Manager (klik op het plaatje voor een grotere weergave)
In de IIS management-tool wordt een groot deel van het scherm in beslag genomen door de “Features View”, het middelste deel dat in de screenshot hierboven te zien is. We kunnen nog steeds schakelen naar de “Content View” zodat we ook zien welke bestanden er in de webapplicatie zijn opgenomen. Via de Features kunnen we evenwel allerlei beheerstaken uitvoeren.
Zodra we dubbelklikken op één van de icoontjes kunnen we zien dat, in tegenstelling tot vorige versies van IIS, de instellingen in het hoofdvenster kunnen worden beheerd. Dat scheelt een hoop zoeken naar tabbladen, dialoogschermen en wizards. Pop-up dialoogschermen zijn er nog wel, maar een stuk minder irritant.
Een ander aspect van de tool is de “Actions” deel. Dit schermdeel toont de meest voor de hand liggende taken die relevant zijn voor het geselecteerde object. Hieronder zien we er een voorbeeld van wanneer de Default website is geselecteerd.

Figuur 2: Met behulp van Actions kunnen we de meest voor de hand liggende taken voor het geselecteerde object uitvoeren.
Modulaire opbouw
IIS heeft lange tijd een negatief imago gehad wanneer het gaat om veiligheid. In het begin was het geïnstalleerd of niet, en als het geïnstalleerd was stonden alle features aan. In IIS 6 werden de features standaard niet aangezet, maar wel geïnstalleerd. In IIS 7 gaan we weer een stap verder en zijn de individuele features los te installeren, zoals in het volgende scherm.

Figuur 3: Een reeks van rollen kunnen afzonderlijk geïnstalleerd worden.
Bovendien gaat de modulaire opbouw nog verder. Ieder request aan de web server kan door één of meerdere modules worden afgehandeld, zoals te zien is in het volgende scherm.

Figuur 4: Via modules is het mogelijk zeer nauwkeurig vast te stellen op welke manier http-requests moeten worden afgehandeld.
Met behulp van deze Modules feature pagina is het mogelijk om modules te beheren die specifieke taken moeten uitvoeren in de request-verwerking zoals authenticatie of compressie.
Dat betekent ook dat de verwerking van requests op een geheel nieuwe manier is vormgegeven. In IIS 6 ging de verwerking zoals te zien in de volgende figuur.

Figuur 5: De request-pipeline van IIS 6.
Een request aan ASP.NET wordt in IIS 6 eerst verwerkt door IIS en daarna doorgestuurd aan de ASP.NET ISAPI DLL. Deze ISAPI bevatte de ASP.NET request pipeline en het pagina framework. Requests aan non-ASP.NET pagina’s, zoals klassiek ASP of statische pagina’s worden afgehandeld door IIS of andere ISAPI extensies die onzichtbaar waren voor ASP.NET.
Het lastige van dit model is dat programmacode in de vorm van ASP.NET modules en ASP.NET webapplicaties niet beschikbaar was in de niet-ASP.NET code en andersom. ASP.NET modules waren dus niet in staat om verwerking door IIS te manipuleren in de stappen vóór of na de ASP.NET afhandeling.
Om deze beperking te verhelpen is de ASP.NET verwerking een integraal onderdeel van IIS 7 in plaats van een plug-in. Dit is zichtbaar in de volgende figuur.

Figuur 6: De request-pipeline in IIS 7.
Een request voor iedere vorm van content (plaatjes, statische html, ASP.NET, web services) wordt afgehandeld door IIS waarbij zogenaamde native modules maar ook .NET modules het request op ieder moment kunnen raken. Op deze manier kunnen we bijvoorbeeld Forms Authenticatie of Output caching ook gebruiken voor klassieke ASP pagina’s en zelfs PHP of statische html.
Het is ook mogelijk om te schuiven in de volgorde van afhandeling zodat het bijvoorbeeld mogelijk is om in ASP.NET een basic authentication-module te schrijven die het Membership-provider model gebruikt en eigen database om het basic authentication mechanisme, dat gebruik maakt van Windows accounts, te vervangen.
Compatibel blijven met IIS 6
Het nieuwe verwerkingsmodel van IIS 7 is natuurlijk mooi voor nieuwe webtoepassingen die er gebruik van willen maken, maar met bestaande toepassingen kan het voor complicaties zorgen, bijvoorbeeld wanneer via WMI specifieke IIS 6 functionaliteit wordt aangesproken. Gelukkig kunnen we bestaande ASP.NET toepassingen toch zonder veel moeite onder IIS 7 laten werken.
Ten eerste kunnen we nog steeds gebruik maken van de management interface API voor IIS 6 door deze rollen te installeren via de server manager.

Figuur 7: IIS 6 Management APIs zijn apart installeerbaar in Windows Server 2008.
Daarnaast kunnen we per application pool instellen of we requests op de oude (classic) manier, via de aspnet_isapi.dll, willen laten verwerken of de nieuwe, integrated, modus.

Figuur 8: Per application pool kunnen we de request-verwerking instellen.
En tot slot kunnen we de configuratie van een webapplicatie aanpassen zodat deze werkt aan de hand van de nieuwe integrated modus. Het valt direct op wanneer de configuratie niet geschikt is voor de integrated modus door de volgende melding.

Figuur 9: Een duidelijke foutmelding vertelt ons wat er aan de hand is met de webapplicatie.
Overigens zijn de foutmeldingen die IIS 7 toont al een stuk beter te begrijpen dan de foutmelding die IIS 6 en eerder weergeeft. Bovendien wordt een suggestie gedaan om het probleem op te lossen. In dit geval helpt de volgende commandoregel:
appcmd migrate config "BlogEngine/"
Hierdoor wordt een <system.webServer> sectie toegevoegd aan Web.Config zodat de webapplicatie in integrated modus kan functioneren.
Zelf modules maken
We hebben al eerder gezien dat het mogelijk is om modules te selecteren en te configureren in de IIS magament tool. Dat kunnen native modules (veelal in C++ geschreven) zijn of .NET modules. Het ligt voor de hand om eens verder te kijken naar mogelijkheden om modules in C# of VB.NET te schrijven. Overigens is het nog steeds mogelijk om ook handlers te schrijven.
Een module is vergelijkbaar met ISAPI filters zoals we ze kennen in vorige versies van IIS. Zo’n module implementeert de System.Web.IHttpModule interface en gebruikt de System.Web namespace om onderdeel uit te maken van de request-verwerking.
Een handler kennen we ook als een ISAPI extensie uit vorige IIS versies en kan je verantwoordelijk maken voor de afhandeling van een bepaald soort request, bijvoorbeeld voor html-content of plaatjes. Het belangrijkste verschil met een module deze geconfigureerd wordt om requests met een bepaalde extensie (.aspx, .gif, .php) af te handelen. Een module heeft daarentegen een veel grotere scope en is toepasbaar op ieder request, ongeacht te extensie.
Omdat we met IIS 6 al in staat waren eenvoudig ASP.NET handlers te schrijven, kijken we nu eens naar modules.
We beginnen met een Class Library project in Visual Studio 2008. Deze versie van Visual Studio is praktisch omdat we hier gelijk beschikken over het .NET 3.x Framework. Daarmee kunnen we namelijk IIS 7 specifieke ASP.NET klassen gebruiken. Het .NET 3.0 Framework is onderdeel van Windows Vista en Windows Server 2008. Het is dus strict genomen ook mogelijk om een IIS 7 module te ontwikkelen op een oudere versie van Windows, als we maar het .NET 3.0 Framework hebben. En zelfs dat is alleen maar nodig voor mogelijkheden als: HttpServerUtility.TransferRequest, de HttpResponse.Headers collectie, het HttpApplication.LogRequest event en een nog een paar anderen.
Voor het voorbeeld gebruiken we Visual Basic .NET, maar C# is natuurlijk ook mogelijk. De naam van het class-module project is DevTips.IIS.DemoModule. We voeg direct een referentie toe aan System.Web.
Dan volgen deze stappen:
- Verwijder Class1.vb
- Voeg een nieuwe klasse toe: FooterModule
- Zet bovenaan: Imports System.Web
- Zet onder de klasse-naam: Implements IHttpModule en druk op enter. We zien dat er automatisch twee methoden worden toegevoegd: Dispose en Init
Imports System.Web
Public Class FooterModule
Implements IHttpModule
Public Sub Dispose() Implements System.Web.IHttpModule.Dispose
End Sub
Public Sub Init(ByVal context As System.Web.HttpApplication) _
Implements System.Web.IHttpModule.Init
End Sub
End Class
De Dispose-methode wordt gebruikt om eventuele unmanaged bronnen op te ruimen wanneer de module klaar is. Wanneer de garbage collector voorbij komt om de instantie van de module op te ruimen moeten die bronnen immers wel vrij zijn. Meestal laten we deze methode overigens leeg.
De Init-methode is wel belangrijk omdat deze de initialisatie van de module zijn haar rekening neemt. Bovendien wordt de module dan gekoppeld aan één of meer events in de requestverwerking die in de HttpApplication klasse zitten. Er staan veel events tot onze beschikking.

Figuur 10: Een reeks events maakt het mogelijk om elke stap van de request-verwerking te onderscheppen.
Aan de hand van de naam van het event kunnen we zien binnen welke stap in de verwerking de event handler haar werk kan doen. Op de IIS.NET website staat een volledige lijst van events en hun volgorde.
Het is dus slechts een kwestie van het koppelen van een eventhandler aan deze events om onze module aan het werk te zetten.
Public Sub Init(ByVal context As System.Web.HttpApplication) _
Implements System.Web.IHttpModule.Init
AddHandler context.BeginRequest, AddressOf StartVerwerking
AddHandler context.EndRequest, AddressOf EindeVerwerking
End Sub
De code toont hoe we twee eventhandlers opgeven voor het BeginRequest en EndRequest event. De implementatie van deze eventhandlers is eenvoudig. Eerst declareren we op klasse-niveau een variabele om de tijd vast te houden.
Private m_startTime As DateTime
Dan implementeren we de methoden StartVerwerking en EindeVerwerking.
Public Sub StartVerwerking(ByVal sender As Object, ByVal e As EventArgs)
m_startTime = DateTime.Now
End Sub
Public Sub EindeVerwerking(ByVal sender As Object, ByVal e As EventArgs)
Dim app As HttpApplication = CType(sender, HttpApplication)
Dim request As HttpRequest = app.Context.Request
Dim processTekst As String = _
"<center><b>Tijd op server: {0}. " & _
"Verwerkingstijd: {1} milliseconden.</b></center>"
app.Context.Response.Write( _
String.Format(processTekst, _
DateTime.Now.ToString("hh:mm:ss"), _
DateTime.Now.Subtract(m_startTime).Milliseconds))
End Sub
Wat wellicht opvalt is dat een instantie van HttpApplication wordt doorgegeven via de sender-parameter in de eventhandlers. We kunnen de rest van het request en response objectmodel vervolgens uit deze instantie van HttpApplication halen via het HttpContext object.
Het gebruik van deze module zal er voor zorgen dat ieder request onderaan de tijd op de server en de verwerkingstijd van het request laat zien. Voor het zover is, moeten we de module nog activeren in IIS. We kunnen de assembly registreren in de global assembly cache (GAC), maar daarvoor moeten we deze een strong name toekennen. Doen we dat niet, dan kunnen we de DLL ook in de bin-folder van de website plaatsen waar de module haar werk moet doen.
Daarna voegen we de module toe via de IIS management tool.
- Selecteer eerst de website
- Dubbelklik op Modules in het Feature-scherm
- Kies bij Actions voor ‘Add Managed Module...’

Figuur 11: Managed modules zijn zichtbaar via de Global Assembly Cache of de lokale /bin-folder.
In het dialoogscherm vullen we een arbitraire maar logische naam in voor de module en selecteren dan uit de lijst onze eigen module. De module zal vervolgens zichtbaar worden in de lijst van modules, onder een aparte ‘Local’ sectie.
Wanneer we nu een webpagina openen van de site waarin we de module geconfigureerd hebben, zien we onderaan extra informatie staan.

Figuur 12: De module laat onderaan de tijd van de server en de verwerkingstijd zien.
Conclusie
Zoals we gezien hebben is er veel veranderd in IIS 7 waardoor het webhosting platform een stuk flexibeler is geworden. Nu IIS 7.0 beschikbaar is in Windows Server 2008 wordt het tijd om er als ontwikkelaar van te profiteren.
Meer informatie