Session
ViewState
Cookie
Børre Stenseth
Moduler>Sesjoner

Sesjoner

Hva
Fire varianter av sesjonskontroll

Vi vet at http-protokollen er tilstandsløs. Det vil si at hver gang det går en melding fra klient til tjener eller omvendt så er dette en begivenhet som ikke er koplet til tidligere begivenheter på noen som helst måte. Når vi skal lage nettløsninger som involverer brukeren i en dialog med mer en ett spørsmål - ett svar, så må vi etablere en form for hukommelse som gjør at stegene i dialogen kan bygge på tidligere steg.

Prinsippielt kan vi etablere denne hukommelsen enten hos klienten eller hos serveren, eller hos begge. Hver av partene kan sende/bruke sin historiekunnskap som en del av sitt bidrag til dialogen.

I denne modulene skal vi ta for oss et svært enkelt eksempel på en 3-stegs dialog og se hvordan vi kan holde styr på en slik sesjon ved hjelp av litt forskjellige mekanismer.

Dialogen er svært enkel. Anta en forening med en åpningsside. Fra denne siden inviteres leseren til å tegne medlemsskap. Dette går i tre steg:

  1. Brukeren bes oppgi navn.
    "Hva heter du ?"
  2. Brukeren bes oppgi alder.
    "Hei Jens, hvor gammel er du ?"
  3. Brukeren bes kvittere på at navn og alder er ok.
    "Registrere Jens, 214 år ?"

Det er åpenbart at dette kunne og burde vært slått sammen til ett eller høyden to steg, men vi trenger et enkelt eksempel og kjører som vist. Vi kan illustrere gangen i det slik:

plan

Det interessante er å se på de vevsidene som realiserer steg1, steg2 og steg3.

Cookies

Du kan teste denne løsningen herhttp://donau.hiof.no/borres/dn/foreningcookie/

Cookies er små meldinger i form av tekst som kan plasseres hos klienten, enten i klientens nettleser eller på klientens harddisk. I dette eksempelet plasserer vi den i klientens nettleser. det vil si at hukommelsen som lagres i cookien varer så lenge nettleseren er oppe. Når vi fra tjeneren skal plassere en cookie hos klienten sender vi den som en del headeren i et http-svar. Koden som lager en cookie og sender den er svært enkel:

HttpCookie cookie = new HttpCookie("TheName");
cookie["Navn"] = Navn;
Response.Cookies.Add(cookie);
	

Det er objektet Response som representerer http-svaret.

Første steg, en vevside som ber om og tar imot navnet.

public partial class _Member : System.Web.UI.Page 
{
    protected void Page_Load(object sender, EventArgs e)
    {
    }
    protected void OK_Click(object sender, EventArgs e)
    {
        string Navn = TextBoxName.Text;
        if(Navn.Length==0)
            Response.Redirect("Default.htm");
        HttpCookie cookie = new HttpCookie("TheName");
        cookie["Navn"] = Navn;
        Response.Cookies.Add(cookie);
        Response.Redirect("Member2.aspx");
    }
    protected void Cancel_Click(object sender, EventArgs e)
    {
        Response.Redirect("Default.htm");
    }
}

Annet steg, en vevside som ber om og tar imot alderen til en med kjent navn.

public partial class Member2 : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        HttpCookie cookie = Request.Cookies["TheName"];
        String Navn = "Metusalem";
        if (cookie != null)
            Navn = cookie["Navn"];
        Label1.Text = "Velkommen " + Navn;
    }
    protected void Cancel_Click(object sender, EventArgs e)
    {
        Response.Redirect("Default.htm");
    }
    protected void OK_Click(object sender, EventArgs e)
    {
        HttpCookie cookie = new HttpCookie("TheAge");
        cookie["Alder"] = TextBox1.Text;
        Response.Cookies.Add(cookie);
        Response.Redirect("Member3.aspx");
    }
}

Tredje steg, en vevside som ber om kvittering på kjent navn og alder.

public partial class Member3 : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        String Navn = "Metusalem";
        String Alder = "1000";
        HttpCookie cookie = Request.Cookies["TheName"];
        if (cookie != null)
            Navn = cookie["Navn"];
        cookie = Request.Cookies["TheAge"];
        if (cookie != null)
            Alder = cookie["Alder"];
        Label2.Text = Navn + "," + Alder;
    }
    protected void Cancel_Click(object sender, EventArgs e)
    {
        Response.Redirect("Default.htm");
    }
    protected void OK_Click(object sender, EventArgs e)
    {
        // save is not implemented
        Response.Redirect("Thanks.htm");
    }
}

Post

Du kan teste denne løsningen herhttp://donau.hiof.no/borres/dn/foreningqstring/

I denne løsningen benytter vi oss av at vi kan sende med data til en vevside. Vi kjenner formatet:

http://donau.hiof.no/borres/dn/foreningqstring/Member3.aspx?navn=jens&alder=12
	

Der ? annonserer at det kommer data og navn=data sett skilles med &. Svakheten er at det er begrenset hva slags tegn vi kan sende i data-delen og hvor mye data vi kan sende. Formatproblemet lar seg lang på vei løse ved å kode data på en slik måte at tegn som kan skape problemer erstattes med vedtatte tegnkombinasjoner.

Når vi skal lese slike parametere hos tjeneren bruker vi klassen Request, f.eks. slik:

String s=Request.QueryString["Navn"];
	

og vi kan sende data slik:

String s = String.Format("Member3.aspx?navn={0}", Request.QueryString["Navn"]);
Response.Redirect(s);	

Første steg, en vevside som ber om og tar imot navnet.

public partial class _Member : System.Web.UI.Page 
{
    protected void Page_Load(object sender, EventArgs e)
    {
    }
    protected void Button1_Click(object sender, EventArgs e)
    {
        string Navn = TextBoxName.Text;
        if(Navn.Length==0)
            Response.Redirect("Default.htm");
        String s = "Member2.aspx?navn=" + Navn;
        Response.Redirect(s);
    }
     protected void Button2_Click(object sender, EventArgs e)
    {
        Response.Redirect("Default.htm");
    }
}

Annet steg, en vevside som ber om og tar imot alderen til en med kjent navn.

public partial class Member2 : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        Label1.Text = "Velkommen " + Request.QueryString["Navn"];
    }
    protected void Cancel_Click(object sender, EventArgs e)
    {
        Response.Redirect("Default.htm");
    }
    protected void OK_Click(object sender, EventArgs e)
    {
        String s = String.Format("Member3.aspx?navn={0}&alder={1}", 
            Request.QueryString["Navn"], TextBox1.Text);
        Response.Redirect(s);
    }
}

Tredje steg, en vevside som ber om kvittering på kjent navn og alder.

public partial class Member3 : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        Label2.Text = 
            Request.QueryString["Navn"] + "," + Request.QueryString["Alder"];
    }
    protected void Cancel_Click(object sender, EventArgs e)
    {
        Response.Redirect("Default.htm");
    }
    protected void OK_Click(object sender, EventArgs e)
    {
        // save is not implemented
        Response.Redirect("Thanks.htm");
    }
}

Session

Du kan teste denne løsningen herhttp://donau.hiof.no/borres/dn/foreningsession/

I .net etableres the objekter av typen Session som automatisk følger en dialog. en slik session lever som en prosess på tjeneren og kjenner igjen forspørsler fra samme klient. En slik session lever default 20 minutter, men kan settes til å leve mer eller mindre. Vi kan sette og finne sessiondata slik:

Session["Navn"] = Navn;
...
String s=(String)Session["Navn"];
	

Første steg, en vevside som ber om og tar imot navnet.

public partial class _Member : System.Web.UI.Page 
{
    protected void Page_Load(object sender, EventArgs e)
    {
    }
    protected void OK_Click(object sender, EventArgs e)
    {
        string Navn = TextBoxName.Text;
        if(Navn.Length==0)
            Response.Redirect("Default.htm");
        Session["Navn"] = Navn;
        Response.Redirect("Member2.aspx");
    }
     protected void Cancel_Click(object sender, EventArgs e)
    {
        Session.Abandon(); 
        Response.Redirect("Default.htm");
    }
}

Annet steg, en vevside som ber om og tar imot alderen til en med kjent navn.

public partial class Member2 : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        String Navn = (String)Session["Navn"];
        Label1.Text = "Velkommen " + Navn;
    }
    protected void Cancel_Click(object sender, EventArgs e)
    {
        Session.Abandon(); 
        Response.Redirect("Default.htm");
    }
    protected void OK_Click(object sender, EventArgs e)
    {
        Session["Alder"] = TextBox1.Text; ;
        Response.Redirect("Member3.aspx");
    }
}

Tredje steg, en vevside som ber om kvittering på kjent navn og alder.

public partial class Member3 : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        string Navn = (String)Session["Navn"];
        string Alder = (String)Session["Alder"];
        Label2.Text = Navn + "," + Alder;
    }
    protected void Cancel_Click(object sender, EventArgs e)
    {
        Session.Abandon();
        Response.Redirect("Default.htm");
    }
    protected void OK_Click(object sender, EventArgs e)
    {
        Session.Abandon();
        // save is not implemented
        Response.Redirect("Thanks.htm");
    }
}

Viewstate

Du kan teste denne løsningen herhttp://donau.hiof.no/borres/dn/foreningvstateMV/

I de tre løsningene ovenfor er hvert av stegene behandlet av hver sin vevside. I dette tilfellet bruker vi en vevside til alle operasjonene. Vevsiden er delt inn i Views som aktiviseres/deaktivisereres etter behov. Dette blir en ganske kunstig situasjon i dette enkle eksempelet, men det er gjort for at dialogen skal være lik eksemplene over. Fordelen med å bruke en side er at vi kan bruke den automatikken .Net tilbyr for å lagre og transportere innholdet i alle, eller noen, felter på en side. Mekanismen som handterer dette er ViewState. Data som lagres i ViewState transporteres fram og tilbake i alle ledd i dialogen.

I dette eksempelet har vi brukt automatikken og bare latt .Net lagre og transportere innholdet i alle felt på siden. Vi kan skru av denne automatikken og enten velge vilke felt vi vil lagre, eller vi kan lagre navngitte verdier. Dersom vi vil skru av automatisk ViewState og sette bare de vi vil bruke, gjør vi dette på selve vevsiden.

public partial class _Member : System.Web.UI.Page 
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!this.IsPostBack)
            MultiView1.ActiveViewIndex = 0;
    }
    
    protected void OK1_Click(object sender, EventArgs e)
    {
        // first stage, receiving name
        if (TextBoxName.Text.Length > 0)
        {
            MultiView1.ActiveViewIndex = 1;
            Label2.Text = "Velkommen " + TextBoxName.Text;
        }
    }
    protected void OK2_Click(object sender, EventArgs e)
    {
        //second stage, receiving age
        string Navn = TextBoxName.Text;
        string Alder = TextBoxAlder.Text;
        if ((Alder.Length > 0) && (Navn.Length > 0))
        {
            Label4.Text = "F�lgende vil bli registret: " + Navn + "," + Alder;
            MultiView1.ActiveViewIndex = 2;
        }
    }
   protected void OK3_Click(object sender, EventArgs e)
    {
        // Save is not implemented
        // These are still valid:
        // TextBoxName.Text
        // TextBoxAlder.Text
        Response.Redirect("Thanks.htm");
    }
    
    protected void Cancel1_Click(object sender, EventArgs e)
    {
        // first stage, cancelling
        Response.Redirect("Default.htm");
    }
    protected void Cancel2_Click(object sender, EventArgs e)
    {
        // second stage, cancelling
        Response.Redirect("Default.htm");
    }
    protected void Cancel3_Click(object sender, EventArgs e)
    {
        // third stage, cancelling
        Response.Redirect("Default.htm");
    }
 }
Referanser
  • Cookie-løsning:
    https://svn.hiof.no/svn/psource/Csharpsites/foreningcookie
  • Query-løsning:
    https://svn.hiof.no/svn/psource/Csharpsites/foreningqstring
  • Session-løsning:
    https://svn.hiof.no/svn/psource/Csharpsites/foreningsession
  • ViewState-løsning:
    https://svn.hiof.no/svn/psource/Csharpsites/foreningvstateMV
Vedlikehold

B.Stenseth, jan 2006

(Velkommen) Moduler>Sesjoner (JavaScript)