Grundkurs asp.net del 4 - sessions
Förord
Sedan det förra kapitlets publicering har .NET Framework Beta 1 släppts av Microsoft. I och med detta döptes det som tidigare kallades ASP+ om till ASP.NET (vilket alltså även denna kurs gjorde). En effekt av detta är att kod som skrivits för PDC Preview versionen kanske inte längre fungerar. De exempel som fanns med i de tidigare kapitlen har kontrollerats och fungerar. På adressen http://aspx1.brinkster.com/hedgate/ kan de testköras och man kan även se koden till dem. Det är den kod som finns med i artiklarna, med lite förbättringar för läsbarhet. Tänk på att de ligger på en gemensam server för massor av ASP.NET testsidor, och det finns inga garantier för att den är uppe. Dessutom är det ju en beta... Om inte sidorna fungerar är det alltså bara att försöka igen, jag har sett att de har fungerat.
Application och Session
Precis som i klassisk ASP så finns det i ASP.NET applikationer och sessioner. Man refererar precis som tidigare till dem med nyckelorden Application och Session. 'Under huven' fungerar det så att det är Page-klassen i ASP.NET som har (bl a) dessa två properties, vilka (via HttpContext-objektet som skapas för varje anrop till servern) pekar på en instans av klassen System.Web.HttpApplicationState respektive System.Configuration.Web.SessionState. Dessa klasser har de egenskaper och metoder vi är vana vid från klassisk ASP, plus en del mer. De har även varsin kollektion där de s k 'applikations-' och 'sessionsvariablerna' sparas.En applikation definieras som alla de filer som finns placerade i en webbrot och dess underkataloger, undantaget de som är applikationer själva (dvs virtuella mappar). Applikationen startar första gången en klient anropar en sida i applikationen, och avslutas inte förrän servern stoppas. Den används till att dela resurser mellan olika sidor i applikationen. Exempelvis kan man i applikationen definiera vissa konstanter, vilka sedan är tillgängliga på alla sidor. Observera att applikationen ej är gemensam för flera maskiner i en webbfarm (till skillnad från sessioner, se nedan).
När en ny klient anropar applikationen skapas en session för denna. Varje klient kör alltså i en egen session, vilken 'lever' så länge som klienten är aktiv. Sessioner i ASP.NET skiljer sig på flera viktiga punkter från de i klassisk ASP:
- Sessionshanteringen kan ligga i en egen process, vilket gör att den 'överlever' även om IIS går ner
- Sessionshanteringen är skalbar och kan läggas på flera maskiner och/eller flera processorer
- Sessioner i klassisk ASP hanteras så att sessionsId:et lagras i en cookie som skickas mellan klienten och servern, så att servern ska veta vilken sessionsdata den ska arbeta med. I ASP.NET är sessionshanteringen inte beroende av cookies (men den kan vara om man vill, vilket även är default)
Se nedan under konfigurering för mer information om vad och hur man kan konfigurera sessioner i ASP.NET.
Precis som i klassisk ASP kan man skriva kod för att hantera applikations- och sessionsglobala händelser. Dessa skrivs i ASP.NET i en fil som kallas Global.asax, vilken placeras i applikationsroten.
Man kan exempelvis skapa ett shoppingvagnsId för nya kunder när en session startas. Både applikations- och sessionsdata ligger alltså på servern. Applikationsdatan är specifik för den enskilda webbservern (och bör alltså därför skapas likadant på alla maskinerna i en webbfarm), till skillnad från sessionsdatan som (kan) delas mellan olika maskiner.
Statebag
De som jobbat med Webclasses eller DHTML-klienter i VB6 känner säkert igen begreppet statebag eller propertybag (som det heter i åtminstone DHTML-klienter). Detta är tillståndsdata (eng. state) som skickas mellan server och klient i request/response-objekten när man laddar om en sida. Den kan användas av utvecklaren i kod genom att lagra information, t ex om klienten utfört något eller ej (se exempel 1), men den används också automatiskt av serverkontroller i ASP.NET. De har en egenskap som heter MaintainState (som är satt till True som default), eftersom den finns på System.Web.UI.Control som alla serverkontroller ärver från.
<script Language="VB" runat="server">
Sub Page_Load(sender As Object, e As EventArgs)
If (Not IsPostBack) Then
State("status") = "Innan"
End If
Dim status As String = State("status").ToString()
innan.Text = status.ToString()
State("status") = "Efter"
status = State("status").ToString()
efter.Text = status.ToString()
End Sub
</script>
Statebag
Konfigurering av ASP.NET applikationer
Konfigurering är en av de riktigt stora styrkorna med ASP.NET. Det är så enkelt som att ändra i en textfil, och det är dessutom fullständigt utbyggbart (eng. extensible). Konfigurering görs i XML-form i en vanlig textfil, config.web. Denna fil bevakas av ASP.NET, så att ändringar införs automatiskt utan att man behöver starta om servern. Man kan applicera konfiguration i tre nivåer. Ytterst finns en maskinglobal konfiguration, vilken ligger i WinNT\Microsoft.NET\Framework\Rotelementet i config.web är taggen
<-- här följer normalt flera andra hanterare -->
Sedan följer de sektioner som 'deklarerats' i configsections, antingen i den config.web som sektionen finns i eller i en config.web i någon högre nivå. Browsercaps-sektionen innehåller t ex information om vad olika browsers klarar av, exempelvis om de kan hantera javascript, frames etc. Detta är ett exempel på hur en browsercaps-sektion kan se ut.
Sessionskonfiguration
Sektionen
mode="inproc"
cookieless="false"
timeout="20"
sqlconnectionstring="data source=127.0.0.1;user id=sa;password="
server="127.0.0.1"
port="42424"
/>
Man kan sedan ändra inställningarna enligt följande:
- mode: Giltiga värden för mode är inproc, sqlserver och stateserver. Här visar man var man vill att ASP.NET ska spara sessionsinformation. Om mode="inproc" så fungerar sessionen som i klassisk ASP, dvs den körs på samma maskin och i samma procedur som IIS. Om webbservern går ner så försvinner all sessionsdata. Det innebär också att man inte kan använda sessioner i webbfarmar, eftersom varje IIS håller sin egen sessionsdata. För att hantera dessa problem kan man använda mode="stateserver" vilket betyder att sessioner kör i en egen process (vilken då måste startas, med kommandot "net start aspstate") vilken t o m kan ligga på en annan maskin än den IIS kör på. Då kan IIS eller t o m hela maskinen som webbservern kör på gå ner utan att sessionsdatan försvinner, och flera olika webbservrar kan använda samma maskin som sessionshanterare, så att det kvittar vilken maskin i en webbfarm som en ASP.NET-sida exekveras på. Om man istället använder mode="sqlserver" så används en SQL Server databas för att lagra och hantera sessionsdatan, istället för aspstate-tjänsten som används vid mode="stateserver". Resultatet blir ju dock ungefär detsamma, flera maskiner kan utnyttja samma sessionshanterare och sessionerna överlever även om en eller flera webbservers går ner. Självklart blir det en viss prestandaskillnad, eftersom webbservern måste gå över nätverket till en annan maskin för att läsa/skriva sessionsdata, eller åtminstone till en annan process på samma maskin.
- cookieless: Kan sättas till antingen "true" eller "false". False är som i tidigare ASP att sessionsId skickas i cookies mellan klienten och servern. Om man däremot sätter den till true så kommer ASP.NET att 'ändra' alla länkar och URL:er inom siten, så att man i anropet till webbservern skickar med sitt sessionsId. En länk som i koden i ASP.NET-sidan har adressen href="kapitel3/exempel1.aspx" kan i HTML-koden som skickas till klienten ändras till href="(dnqynpfhkmwvhq45i4s1i5ue)/kapitel3/exempel1.aspx". Utan att man som utvecklare behövt koda en rad kan man nu ha sessioner även för besökare som inte stödjer/vill ha cookies.
- timeout: Antal hela minuter som sessioner ska leva i.
- sqlconnectionstring: Om mode="sqlserver" så skriver man in connectionsträngen för att koppla sig till den server som ska hantera sessionsdatan.
- server: Om mode="stateserver" anger man här vilken maskin som ASP.NET ska anropa för sessionshantering.
- port: = Här anges på vilken port man ska anropa den stateserver som angivits i server.
Caching
Caching är en kraftfull teknik för att öka prestanda genom att lagra information som används ofta eller tar mycket kraft att skapa i minnet, så att man slipper skapa det för varje anrop. ASP.NET tillhandahåller två typer av caching, output cache och data cache. Output cache
Output cache innebär att ASP.NET lagrar resultatet av en exekvering av en .aspx-sida, dvs den HTML som skickas till klienten, så att sidan inte behöver exekveras nästa gång någon anropar den, utan ASP.NET kan plocka den lagrade HTML-koden och skicka direkt. Output caching är som standard påkopplat i ASP.NET, men en sida cachas inte om man inte explicit markerar att den ska göra det. Det gör man genom att på sidan som ska cachas ange följande direktiv:
<%@ OutputCache Duration="100" %>
Detta direktiv säger åt ASP.NET att resultatet av denna sidan ska cachas, och det ska 'leva' i 100 sekunder. När 100 sekunder har gått så kommer ASP.NET att plocka bort det från cachen igen. Alla GET och HEAD anrop som görs på sidan fram till dess kommer att få det resultat som lagrats i cachen skickat till sig utan att ASP.NET behöver exekvera sidan. Ett POST anrop får aldrig resultat från cachen, utan sidor som anropas med POST exekveras alltid. ASP.NET stödjer dessutom att man skickar querystring-parametrar i ett GET-anrop och kommer då att lagra resultatet av en exekvering med vissa parametrar som ett annat resultat än det skapat med andra parametrar. Om man t ex har en länksamling med olika kategorier, med länkar som ser ut så här:
Programmeringssiter
Diskussionsforum
Då kommer ASP.NET se till att man inte får fel länkar (dvs från fel kategori). Om en viss kategori inte valts på ett tag kommer den att exekveras och resultatet lagras i cachen, märkt på ett sånt sätt att ASP.NET inte kommer att skicka det till någon som efterfrågar en annan kategori.
Data cache
Data cache är till skillnad från output cache något som används av utvecklaren i .aspx-koden. Den används för att lagra data som används på webbsidorna, t ex tabell som skapas från en SQL-fråga. I enklaste form kan det se ut så här (endast den intressanta koden är med):
Dim MinTabell As DataView
MinTabell = Cache("mintabell")
If (MinTabell = Nothing) Then
''' Skapa DataSet (ds) från databas '''
MinTabell = New DataView(ds.Tables("min_tabell_i_databasen"))
Cache("mintabell") = MinTabell
End If
MinDataGrid.DataSource = MinTabell
MinDataGrid.DataBind()
Som ni ser så försöker ASP.NET först läsa in datan från cachen. Om det misslyckas (MinTabell = Nothing) så skapar den datan genom att anropa en databas och lägger den data som returneras i cachen, men detta görs alltså inte om datan fanns i cachen redan från början. Slutligen så visas datan på sidan genom att den binds till en DataGrid-kontroll. Detta exempel visade ett exempel på vanlig, enkel caching. Denna data kommer att ligga i cachen till dess att man manuellt ändrar den (genom att lägga dit något annat), eller att cachen 'dör'. Cachen är applikationsberoende, så om man stoppar en applikation så nollställs cachen. För lite mer avancerad form av data caching så stödjer ASP.NET tre varianter: scavenging, expiration och file/key dependency.
- Scavenging betyder ungefär rensning eller städning. Det innebär att ASP.NET kommer att plocka bort cachad data som inte används särskilt ofta när det blir ont om minne. Man kan programmatiskt när man cachar data ange den relativa kostnaden för att skapa just den datan samt hur mycket den ska utnyttjas för att anses vara viktig att behålla.
- Expiration innebär att man sätter en tidpunkt som visar hur länge datan gäller. Det kan göras både absolut och relativt, dvs man kan sätta ett klockslag då den ska plockas bort ur cachen eller ange att den ska 'leva' i t ex 20 minuter från det att den senast använts.
- Det tredje alternativet, som också är det mest kraftfulla, är s k file/key dependency. Här anger man när man lägger in data i cachen att den ska vara beroende av en fil, eller någon annan data i cachen. Som exempel kan man tänka sig en applikation som får valutakurser en gång om dagen, vilka skickas via FTP i en XML-fil. När filen uppdateras plockas datan automatiskt bort ur cachen och nästa gång man vill använda den läses in igen och lagras i cachen. Ett något enkelt exempel kan se ut så här (endast den väsentliga delen av koden visas, hela exemplet kan ses på den adress som anges överst i artikeln):
'Data caching med filberoende
CurrencyData = Cache("currencies")
If (CurrencyData = Nothing)
Dim fs As FileStream
Dim sr As StreamReader
Dim ds As DataSet
ds = New DataSet
fs = New FileStream(Server.MapPath("currencies.xml"), & _
FileMode.Open, FileAccess.Read)
sr = New StreamReader(fs)
ds.ReadXml(sr)
fs.Close()
CurrencyData = New DataView(ds.Tables(0))
Cache.Insert("currencies", CurrencyData, & _
New CacheDependency(Server.MapPath("currencies.xml")))
End If
Den viktiga raden är alltså Cache.Insert-anropet. Här anges att ett CacheDependency ska skapas på den fil som står sist. Observera att denna fil inte nödvändigtvis behöver ha något med datan som cachas att göra, utan det är bara den som ska styra när datan ska plockas bort ur cachen. Det viktiga är att ASP.NET automatiskt observerar den fil som angivits som CacheDependency utan att man som utvecklare behöver tänka på när det ska göras. Ett bra exempel på hur detta används i ASP.NET är alla källkodsfiler, vilka konstant övervakas av systemet. När en fil anropas för första gången kompileras den och sedan exekveras den kompilerade koden. Senare anrop exekverar direkt den kompilerade koden. Så fort något ändrats i filen kommer ASP.NET att upptäcka detta och vid nästa anrop till sidan kommer den automatiskt att kompileras om.
Deployment
Att installera och konfigurera en webbsite i klassisk ASP kan vara svårare än man tror ibland. Om man t ex använder COM-objekt i DLL-filer ska dessa registreras, om dessa dessutom är COM+ applikationer ska man in i COM+ Component Services och lägga in dem där. Det riktigt stora bekymret kommer sedan när man ska uppdatera dessa komponenter. Vi är många som slitit vårt hår med dessa bekymmer.Med ASP.NET slipper vi bli korthåriga i förtid (hmm, kanske inte, men inte pga dessa bekymmer åtminstone). Att installera en applikation i ASP.NET är så enkelt som att kopiera filerna som applikationen består av till servern. De DLL-filer som applikationen använder behöver inte registreras, det är bara att lägga dem i /bin katalogen. T o m för komponenter som ska vara COM+ applikationer räcker det att kopiera in dem på plats. Systemet kommer dynamiskt att skapa COM+ applikationen och registrera komponenterna där när den behövs. Detta är inget som är specifikt för ASP.NET utan är funktionalitet som gäller alla .NET applikationer. Sättet som detta fungerar på innebär också att man slipper det som normalt kallas 'DLL Hell', dvs att en applikation slutar fungera för att en annan applikation uppdaterar en komponent som används av bägge programmen.
En applikation i .NET är garanterad att köras med de komponenter den är installerad med. När man vill uppdatera en komponent är det bara att kopiera in den nya DLL-filen (eller motsvarande fil beroende på vad man uppdaterar). ASP.NET låser aldrig DLL-filer genom att ladda dem i minnet som klassisk ASP gör. Istället laddar den en kopia av filen och bevakar sedan filen, så att när filen uppdateras så gör den en ny kopia. På så sätt kan man uppdatera en applikation utan att ens ta ner webbservern.
Sammanfattning kapitel 4
Nu har vi gått genom flera aspekter av ASP.NET på applikationsnivå. Tillsammans med kraftfullheten och flexibiliteten i web forms så är det här som de riktiga styrkorna i ASP.NET ligger. I kapitel 5 avslutar den här artikelserien om ASP.NET med några exempel på saker man kan göra.
Exempel fil
Tanka ner exempel fil till denna artikel Här.
Var denna artikeln användbar?
Om du gör någon intressant (eller kanske något konstigt fel) på grund av detta material så skicka gärna det med ett mail eller bifoga en länk till mig så presenterar jag detta som ytterligare exempelfiler för kursen. Om detta innehållet är felaktigt eller du lärt dig fler finesser så skriv gärna en rad eller varför inte en egen kurs baserat på dina erfarenheter. Sänd gärna in dina tips till denna kurs./Christoffer Hedegate
0 Kommentarer