Et kig på ASP.NETs Page klasse

Tags:    asp.net
Skrevet af Bruger #4522 @ 11.03.2009

.aspx og klassen Page
Når ASP.NET modtager en forespørgsel på en .aspx -side leder den efter den pågældende klasse fra de indlæste assemblies. Hvis den ikke findes, kompileres den fra kildekoden, og indlæses. Efterfølgende forespørgelser på samme klasse bruger så den allerede indlæste klasse - med andre ord kompileres en klasse kun første gang den efterspørges. Hvis der senere rettes i .aspx -koden rekompileres den.

Den klasse der genereres dynamisk og kompileres, nedarver fra Page -klassen. Eller rettere, den nedarver fra den klasse du er med til at skrive, og som nedarver fra Page -klassen.

Lad os kigge på et eksempel. Hvis du tilføjer en Default.aspx side til en ASP.NET applikation, oprettes en fil med en partiel klasse:

Fold kodeboks ind/udCSharp kode 


Ovenstående klasse, er den hvori du skriver den kode der skal håndtere de forskellige events der kan opstå på Default.aspx -siden. Når siden kompileres, genereres den anden del af klassen. Denne del indeholder alle felterne der repræsenterer de forskellige ASP.NET web-server kontroller du har puttet på siden (Button, Panel etc). Den ser sådanne ud:

Fold kodeboks ind/udCSharp kode 


Disse to dele flettes så sammen til én klasse:

Fold kodeboks ind/udCSharp kode 


ASP.NET parser nu denne klasse og genererer den klasse der bruges som respons på anmodningen efter default.aspx:

Fold kodeboks ind/udCSharp kode 


ASP.NET HTTP køretidsmiljøet
Lad os nu træde et par skridt tilbage, og se på hele processen fra begyndelsen af.
Det hele starter med en simpel HTTP pakke, og ender med markup der sendes tilbage til browseren. Det lyder simpelt, men det er en lang og kompliceret proces. En proces der gør brug af en masse objekter, som i et samspil sørger for at genere den nødvendige markup til browseren. Processen w3wp.exe giver HTTP forespørgelsen videre til ASP.NET HTTP køretidsmiljøet som denne lange kæde af forskellige objekter kaldes.

Første stop på denne lange rejse er HttpRuntime.

HttpRuntime
w3wp.exe starter hele ASP.NET pipelinen ved at lave et nyt HttpRuntime -objekt. For hver forespørgsel kaldes objektets ProcessRequest -metode som driver hele ASP.NET systemet. Objektet har også en public metode kaldt Close som sletter ASP.NET cachen. Du skal normalt aldrig kalde denne metode selv - den bruges kun i de meget specielle tilfælde hvor du implementerer dit eget hostingmiljø. Hvis du får brug for at genstarte din ASP.NET applikation kan du kalde UnloadAppDomain som lukker for den igangværende ASP.NET applikation. Næste gang der kommer en forespørgsel på samme applikation genstartes den. Denne metode er også nyttig på servere der har et stort antal ASP.NET programmer kørende, som kun sjældent modtager forespørgselser. I stedet for at bruge resurser på at have disse applikation kørende under hele processen, kan de lukkes ned ved brug af UnloadAppDomain.

HttpRuntime -objektet gør brug af flere hjælpeobjekter: blandt andet en cachemanager der styrer ASP.NET cahcen, og en filovervåger som holder øje med om der sker nogle ændringer i nogle af de filer som udgør applikationen (dette skal nemlig medføre en genstart af applikationen). Et meget vigtigt hjælpebjekt er et objekt af typen HttpContext som indeholder en masse HTTP-specifik information omkring forespørgelsen. HttpRuntime laver også et skriveobjekt hvori al markuppen opsamles (det er denne markup der i sidste ende sendes til browseren).

Næste trin er for HttpRuntine -objektet at finde ud af hvilken applikation forespørgelsen vedrører. Dette gøres ved at undersøge den opgivne URL og så finde den pågældende virtuelle mappe i IIS. For at løse denne opgave bruger HttpRuntime -objektet et objekt af typen HttpApplicationFactory.

HttpApplicationFactory
Ved at undersøge forespørgelsens URL vælger HttpApplicationFactory et passende applikationsobjekt der kan behandle forespørgelsen. Hvis der ikke allerede er oprettet et objekt for den ønskede applikation, oprettes et nyt. Så længe en applikation lever, har HttpApplicationFactory en pulje af HttpApplication -objekter der kan håndtere indkomne HTTP forespørgelser. Et enkelt HttpApplication står for forespørgelsen efter en enkelt side. For at håndtere flere simultane forespørgelser bruges flere objekter.

HttpApplication
En kørende ASP.NET applikation er repræsenteret af et objekt af typen HttpApplication. Såfremt der til applikationen findes en global.asax -fil læses denne, og istedet genereres en klasse der nedarver fra HttpApplication, og som så har indhold fra global.asax.

Et HttpApplication -objekt står for at håndtere hele forespørgelsen, og har adgang til en liste over registreret HTTP moduler den kan/skal bruge i løbet af hele processen til at modificere det respons der sendes til browseren. Da objektet er aktivt under hele processen, kan det først genbruges når svaret er sendt til browseren, og forespørgelsen altså er færdigbehandlet.

HttpApplication -objektet bestemmer hvilken type resurse der efterspørges, og ved hjælp af klasser der implementerer IHttpHandlerFactory opretter den et objekt af den rette type, der så kan hjælpe til med at generere svaret til browsweren. Disse objekter implementerer IHttpHandler interfacet. Så hvis fx. der efterspørges en .aspx -side oprettes én type objekt, mens hvis der efterspørges en brugerkontrol (eng.: user control) oprettes en anden type objekt osv. (som dog alle har det til fælles at de implementerer IHttpHandler).

Følgende (ikke komplet) liste viser hvilke IHttpHandlerFactory -klasser der tager sig af de forskellige ASP.NET resurser:


  • *.rem *.soap : HttpRemotingHandlerFactory

  • *.aspx : PageHandlerFactory

  • *.ashx : SimpleHandlerFactory

  • *.asmx : WebServiceHandlerFactory



Nu er vi i denne artikel hovedsageligt interesseret i Page -klassen. Så lad os se hvad der sker når forespørgelsen er på en .aspx -side.


  1. Vores HttpApplication -objekt er blevet bedt om at håndtere en forespørgsel på en .aspx -side.

  2. Ved at undersøge applikationens konfigurationsfil (specifikt <httpHandlers> elementet), finder HttpApplication -objektet ud af hvilken factory klasse den skal oprette et objekt fra. For en .aspx -resurse skal den oprette et objekt af typen PageHandlerFactory.

  3. Vores factory-objekt skal nu oprette en klasse der implementerer interfacet IHttpHandler, hvilket netop Page -klassen gør. Derfor oprettes nu et objekt (som beskrevet tidligere i artiklen i afsnittet .aspx og klassen Page) der nedarver fra den klasse som du har været med til at skrive, og som repræsenterer den efterspurgte .aspx -side.



Når ASP.NET har genereret en klasse på en .aspx forespørgsel (en klasse der indirekte nedarver fra Page og altså implementerer IHttpHandler -interfacet), vil HTTP køretidsmiljøet bruge denne klasse via grænsefladen defineret i IHttpHandler. Dette interface består kun af to medlemmer, en metode kaldet ProcessRequest, som starter den lange proces der ender med et respons til browseren (denne proces kaldes også for Page -livscyklussen), og en boolsk egenskab kaldt IsReusable som angiver hvorvidt en anden forespørgsel kan bruge dette IHttpHandler objekt.

Nu er vi altså nået så langt i processen at vi er nået hen til noget af den kode du som ASP.NET programmør har skrevet, og nu går hele Page -livscyklussen i gang.


Hvad synes du om denne artikel? Giv din mening til kende ved at stemme via pilene til venstre og/eller lægge en kommentar herunder.

Del også gerne artiklen med dine Facebook venner:  

Kommentarer (1)

User
Bruger #16651 @ 09.10.11 21:11
Virkelig en yderst gennemarbejdet og flot artikel der gennemgår så mange detaljer! BRAVO!!
Du skal være logget ind for at skrive en kommentar.
t