adszone.org
venerdì 20 settembre 2024
"Il modo corretto di pensare il software"
home
consulenza  vb.net  contatti 
  Visual Basic .NET
  Web Forms
Domande

Prima di iniziare, si consiglia di aver ben chiari i concetti relativi ai Form HTML.

ASP.NET: Meccanismi

Quando il web server riceve la richiesta del browser di una pagina HTML, la pagina viene reperita dalla memoria di massa ed inviata direttamente al browser che si occupera' di graficarla.

Dallo schema precedente si osserva che se la pagina richiesta e' una pagina aspx, questa pagina viene prima elaborata e poi fornita al browser. L'elaborazione e' compito di ASP.NET. Come si vede, ASP.NET e' un'estensione del server che si occupa di eseguire il codice presente nella pagina. Il documento effettivamente inviato al browser e' sempre un documento HTML, opportunamente modificato dal codice asp.

Nelle versioni precedenti di asp si potevano aggiungere righe dei codice all'interno del ducumento per mezzo del tag <%... %>. Tale gruppo di righe di codice viene detto Script. E' da notare, comunque, che il miscuglio di codice ASP e tag HTML produce un groviglio di informazioni difficilmente gestibile. Questo groviglio e' soprannominato ironicamente "codice a spaghetti". Pur rendendo ancora possibile questo approccio, ASP.NET fornisce una soluzione piu' elegante.

La soluzione consiste nel trattare la pagina web come fosse un Form, detto Web Form e, come per ogni form, sono disponibili dei controlli che si suddividono in tre categorie:

  • Controlli HTML Server
  • Controlli Web Server
  • Controlli Server per la convalida

E' chiaro che questi controlli vengono abilmente sfruttati in sostituzione degli script. Il codice relativo alla pagina, come vedremo, comparira' altrove. Tutti e tre i tipi di controlli appartengono alla categoria server, cioe' processati da asp prima che la pagina sia inviata. Sul browser essi appariranno come i tipici elementi HTML che siamo abituati a vedere. I controlli HTML Server rappresentano i classici tag HTML che conosciamo, ma hanno la particolare coppia attibuto valore runat="server" che permette ad asp di elaborarli e quindi modificarne le proprieta'. I controlli Web Server sono speciali tag di asp. Anch'essi sono individuati da runat="server" e non corrispondono necessariamente ai classici tag HTML. La loro sintassi e' <asp:nome_controllo id="nome" runat="server"/>. Tra essi riconosciamo la TextBox, la ComboBox, etc. I Controlli per la convalida, servono a convalidare l'input dell'utente in modo che, tramite il form, non vengano inoltrate informazioni non corrette.

L'immagine che segue, da' un'idea di un Web Form con i vari controlli che abbiamo menzionato. Vale la pena far osservare che il concetto di Form implica la persistenza di una stessa pagina. Alla base di questo meccanismo (PostBack), e' previsto che la pagina aspx contenga un solo tag form, anch'esso runat="server". Il trucco e' che l'action del form punti sempre alla stessa pagina. Di conseguenza essa verra' ripresentata con le opportune modifiche ad ogni submit.

Tutti i controlli di cui abbiamo parlato vanno necessariamente inseriti all'interno di tale form. Ma dove' il codice? Segue la pagina aspx relativa al form dell'immagine. Come mostra la prima riga (una direttiva aspx), il codice sta "dietro" ed esattamente nel file "WebForm1.aspx.vb". Questo ed altri file del genere verranno compilati ed inclusi sotto forma di DLL.

<%@ Page Language="vb" AutoEventWireup="false" Codebehind="WebForm1.aspx.vb" 
    Inherits="VBN_Tut_aspnet.WebForm1"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
    <HEAD>
    <title>Generatore Di Onde</title>
    <meta content="Microsoft Visual Studio.NET 7.0" 
        name="GENERATOR">
    <meta content="Visual Basic 7.0" name="CODE_LANGUAGE">
    <meta content="JavaScript" name="vs_defaultClientScript">
    <meta content="http://schemas.microsoft.com/intellisense/ie5" 
        name="vs_targetSchema">
    </HEAD>
    <body MS_POSITIONING="GridLayout" bgColor="white">
    <form id="Form1" method="post" runat="server" >
    
        <asp:RangeValidator id="RangeValidator2" style="Z-INDEX: 108; 
           LEFT: 448px; POSITION: absolute; TOP: 40px" runat="server"  
           ErrorMessage="Non compreso tra 1 e 150" Width="188px">
           </asp:RangeValidator>
           
        <SELECT id="Onda" style="Z-INDEX: 114; LEFT: 408px; WIDTH: 121px; 
            POSITION: absolute; TOP: 104px" name="Onda" runat="server">
        </SELECT>
        
        <DIV style="DISPLAY: inline; Z-INDEX: 113; LEFT: 320px; 
            WIDTH: 72px; POSITION: absolute; TOP: 104px; HEIGHT: 24px" 
            ms_positioning="FlowLayout">Onda:</DIV>
		    
        <DIV style="DISPLAY: inline; Z-INDEX: 112; LEFT: 320px; 
            WIDTH: 72px; POSITION: absolute; TOP: 72px; HEIGHT: 24px" 
            ms_positioning="FlowLayout">Colore:</DIV>
		    
        <DIV style="DISPLAY: inline; Z-INDEX: 111; LEFT: 320px; 
            WIDTH: 72px; POSITION: absolute; TOP: 40px; HEIGHT: 24px" 
            ms_positioning="FlowLayout">Frequenza:</DIV>
            
        <IMG id="Schermo" style="Z-INDEX: 109; LEFT: 7px; 
            POSITION: absolute; TOP: 8px" height="300" alt="" 
            src="" width="300" runat="server">
            
        <asp:RangeValidator id="RangeValidator1" style="Z-INDEX: 107; 
            LEFT: 448px; POSITION: absolute; TOP: 8px" runat="server" 
            ErrorMessage="Non compreso tra 1 e 10" Width="188px">
            </asp:RangeValidator>
            
        <asp:Button id="btnAggiorna" style="Z-INDEX: 106; LEFT: 368px; 
            POSITION: absolute; TOP: 144px" runat="server" Text="Aggiorna">
            </asp:Button>
            
        <asp:RequiredFieldValidator id="RequiredFieldValidator2"
            style="Z-INDEX: 105; LEFT: 448px; POSITION: absolute; TOP: 40px" 
            runat="server" ErrorMessage="Campo vuoto">
            </asp:RequiredFieldValidator>
            
        <asp:RequiredFieldValidator id="RequiredFieldValidator1"
            style="Z-INDEX: 104; LEFT: 448px; POSITION: absolute; TOP: 8px" 
            runat="server" ErrorMessage="Campo vuoto">
            </asp:RequiredFieldValidator>
            
        <SELECT id="Colore" runat="server" style="Z-INDEX: 102; 
            LEFT: 408px; WIDTH: 121px; POSITION: absolute; TOP: 72px">
        </SELECT>
        
        <asp:TextBox id="txtFrequenza" style="Z-INDEX: 101; LEFT: 408px; 
            POSITION: absolute; TOP: 40px" runat="server" Width="32px">
            </asp:TextBox>
            
        <asp:TextBox id="txtAmpiezza" style="Z-INDEX: 100; LEFT: 408px; 
            POSITION: absolute; TOP: 8px" runat="server" Width="32px">
            </asp:TextBox> 
            
        <DIV style="DISPLAY: inline; Z-INDEX: 110; LEFT: 320px; 
            WIDTH: 72px; POSITION: absolute; TOP: 8px; HEIGHT: 24px" 
            ms_positioning="FlowLayout">Ampiezza:</DIV>
    </form>
    </body>
</HTML>
		

L'esempio precedente ci mostra un form con molti controlli al suo interno, alcuni sono controlli Web Server, altri HTML Server ed altri servono alla convalida dei campi di input. Nonostante sia possibile scrivere applicazioni aspx con il notepad "a mano", il Visual Studio 7 permette di automatizzare tutto cio'. I controlli si aggiungono graficamente ed il codice html precedente viene scritto automaticamente.

Il WebForm1.aspx.vb che segue ci mostra il codice che sta dietro al nostro esempio. Notate che e' molto simile ad un progetto VB.NET. In particolare i controlli Server (compreso il Form) generano eventi ed hanno proprieta' accessibili proprio come siamo abituati a fare in VB.NET. Il Click di un pulsante produce il submit con conseguente ricariamento della pagina. A differenza di un'applicazione Form, il Form_Load puo' essere invocato piu' volte, a seconda di quante volte premiamo il pulsante. Il ricaricamento del Form viene detto PostBack e la relativa proprieta' IsPostBack dice al Form se stiamo ricaricando oppure e' la prima volta che elaboriamo il Form. Questo puo' essere utile per eseguire delle istruzioni di inizializzazione soltanto la prima volta. Inoltre, in automatico, ad ogni ricaricamento del Form i controlli mantengono i valori assunti precedentemente. Questo e' possibile grazie al meccanismo detto ViewState. Il ViewState si realizza con un tag input hidden che memorizza le informazioni da ripristinare. Esso puo' essere abilitato o meno. E' abilitato per default.

Public Class WebForm1
    Inherits System.Web.UI.Page
    Protected WithEvents txtFrequenza As System.Web.UI.WebControls.TextBox
    Protected WithEvents txtAmpiezza As System.Web.UI.WebControls.TextBox
    Protected WithEvents Colore As System.Web.UI.HtmlControls.HtmlSelect
    Protected WithEvents RequiredFieldValidator1 As System.Web.UI _
        .WebControls.RequiredFieldValidator
    Protected WithEvents RequiredFieldValidator2 As System.Web.UI _ 
        .WebControls.RequiredFieldValidator
    Protected WithEvents btnAggiorna As System.Web.UI.WebControls.Button
    Protected WithEvents RangeValidator1 As System.Web.UI.WebControls _
        .RangeValidator
    Protected WithEvents Schermo As System.Web.UI.HtmlControls.HtmlImage
    Protected WithEvents Onda As System.Web.UI.HtmlControls.HtmlSelect
    Protected WithEvents RangeValidator2 As System.Web.UI.WebControls _
        .RangeValidator

#Region " Web Form Designer Generated Code "

    'This call is required by the Web Form Designer.
    <System.Diagnostics.DebuggerStepThrough()> Private Sub _
               InitializeComponent()

    End Sub

    Private Sub Page_Init(ByVal sender As System.Object, _
        ByVal e As System.EventArgs) Handles MyBase.Init
        'CODEGEN: This method call is required by the Web Form Designer
        'Do not modify it using the code editor.
        InitializeComponent()
    End Sub

#End Region

    Private Sub Page_Load(ByVal sender As System.Object, _
	    ByVal e As System.EventArgs) Handles MyBase.Load

        If Not Me.IsPostBack Then

            txtAmpiezza.Text = "75"
            txtFrequenza.Text = "5"

            Colore.Items.Add("Verde")
            Colore.Items.Add("Rosso")
            Colore.Items.Add("Blu")
            Colore.SelectedIndex = 0

            Onda.Items.Add("Quadra")
            Onda.Items.Add("Sinusoide")
            Onda.SelectedIndex = 1

            RequiredFieldValidator1.ControlToValidate = "txtAmpiezza"
            RequiredFieldValidator1.InitialValue = ""

            RequiredFieldValidator2.ControlToValidate = "txtFrequenza"
            RequiredFieldValidator2.InitialValue = ""

            RangeValidator1.ControlToValidate = "txtAmpiezza"
            RangeValidator1.MinimumValue = 1
            RangeValidator1.MaximumValue = 150
            RangeValidator1.Type = ValidationDataType.Integer

            RangeValidator2.ControlToValidate = "txtFrequenza"
            RangeValidator2.MinimumValue = 1
            RangeValidator2.MaximumValue = 10
            RangeValidator2.Type = ValidationDataType.Integer

        End If

        Schermo.Src = "image.aspx?"
        Schermo.Src = Schermo.Src & "Colore=" & Colore.Value & "&"
        Schermo.Src = Schermo.Src & "Freq=" & txtFrequenza.Text & "&"
        Schermo.Src = Schermo.Src & "Amp=" & txtAmpiezza.Text & "&"
        Schermo.Src = Schermo.Src & "Onda=" & Onda.Value
    End Sub

End Class

L'esempio che stiamo considerando realizza un generatore di forme d'onda su pagina web. E' possibile impostare i vari parametri e premere il pulsante per aggiornare la figura. Quando il Form viene caricato, elabora i parametri creando un link da assegnare al tag IMG "Schermo" che rappresenta la figura da disegnare. Questa figura non e' un'immagine contenuta in memoria, ma viene creata dinamicamente da un'altra pagina aspx: Image.aspx. Ecco il suo codice.

Imports System.Drawing
Imports System.Drawing.Imaging
Imports System.Math

Public Class image
    Inherits System.Web.UI.Page

#Region " Web Form Designer Generated Code "

    'This call is required by the Web Form Designer.
    <System.Diagnostics.DebuggerStepThrough()> Private Sub _
              InitializeComponent()

    End Sub

    Private Sub Page_Init(ByVal sender As System.Object, _
	    ByVal e As System.EventArgs) Handles MyBase.Init
        'CODEGEN: This method call is required by the Web Form Designer
        'Do not modify it using the code editor.
        InitializeComponent()
    End Sub

#End Region

    Private m_W, m_H As Integer
    Private m_Freq As Integer
    Private m_Amp As Integer
    Private m_Color As Color
    Private m_Onda As String

    Private Sub Page_Load(ByVal sender As System.Object, _
        ByVal e As System.EventArgs) Handles MyBase.Load
        Response.ContentType = "image/gif"
        m_W = 300 : m_H = 300

        m_Freq = Request("freq") 
        m_Amp = Request("amp") 

        If Request("colore") = "Rosso" Then
            m_Color = Color.Red
        ElseIf Request("colore") = "Blu" Then
            m_Color = Color.Blue
        Else
            m_Color = Color.Green
        End If


        m_Onda = Request("onda") 

        Dim Bmp As New Bitmap(m_W, m_H)
        Dim g As Graphics = Graphics.FromImage(Bmp)

        If m_Onda = "Sinusoide" Then
            Sinusoide(g)
        Else
            Quadra(g)
        End If

        Bmp.Save(Response.OutputStream, ImageFormat.Gif)

        g.Dispose()
        Bmp.Dispose()
    End Sub

    Private Sub Sinusoide(ByVal g As Graphics)
        Dim pen As New Pen(m_Color, 1)
        Dim i As Integer, y As Integer

        For i = 0 To m_W - 1
            y = (m_H / 2) - m_Amp * Sin(2 * m_Freq * i * Math.PI / m_W)
            g.DrawLine(pen, i, CInt(m_H / 2), i, y)
        Next
    End Sub

    Private Sub Quadra(ByVal g As Graphics)
        Dim pen As New Pen(m_Color, 1)
        Dim i As Integer, y As Integer

        For i = 0 To m_W - 1
            y = -m_Amp * Sin(2 * m_Freq * i * Math.PI / m_W)

            If y > 0 Then
                y = (m_H / 2) + m_Amp
            Else
                y = (m_H / 2) - m_Amp
            End If

            g.DrawLine(pen, i, CInt(m_H / 2), i, y)
        Next
    End Sub

End Class

Il file Image.aspx finge di essere un'immagine, in realta' la crea con gli oggetti messi a disposizione dalla tecnologia .NET, cioe' GDI+ e la classe Bitmap. Esso salva la bitmap sullo stream, Response.OutputStream, fornendo l'immagine al relativo tag IMG.

Questo form restituira' semplicemente l'immagine dell'onda voluta. Esso dimostra l'utilizzo di due altri oggetti: Request e Response. Request si occupa di reperire le informazioni che hanno generato la richiesta della pagina, in particolare la QueryString. Quando il Form WebForm1 genera l'url dell'immagine, lo fa concatenando i parametri della forma d'onda, es Image.aspx?Colore=Rosso&Freq=3&Amp=75&Onda=Quadra. La parte dell'url dopo il "?" viene detta QuestyString. La interpretiamo come coppie attributo-valore. Alla collection di default dell'oggetto Request forniamo la chiave, che corrisponde all'attributo, e riceviamo il valore. L'oggetto Response e' l'interfaccia con il flusso di dati che il server invia al browser come risposta alla richiesta. Noi, ad esempio, abbiamo restituito il flusso di byte relativo all'immagine.

Oggetti Validator

Poiche' abbiamo utilizzato un paio di TextBox e vogliamo che l'utente fornisca valori coerenti, abbiamo inserito tre oggetti Validator. Tali oggetti non sono visibili normalmente, ma appaiono quando si verifica un errore di input e mostrano il messaggio da noi stabilito, es ErrorMessage="Non compreso tra 1 e 10". Questo messaggio compare quando l'oggetto che contiene il valore da controllare perde il Focus. Ad un oggetto validator 1) si assegna l'oggetto da controllare, 2) gli si imposta l'insieme di valori validi ed 3) il tipo di dato. Il RangeValidator controlla che il valore sia compreso nell'intervallo MinimumValue .. MaximumValue. Il RequiredFieldValidator indica errore se il valore e' vuoto oppure e' quello di default. Tale valore si imposta con la proprieta' InitialValue. Ricapitolando:

		
        ' Sul Form
		
        <asp:RangeValidator id="RangeValidator2" style="Z-INDEX: 108; 
           LEFT: 448px; POSITION: absolute; TOP: 40px" runat="server"  
           ErrorMessage="Non compreso tra 1 e 150" Width="188px">
           </asp:RangeValidator>
           
        <asp:RangeValidator id="RangeValidator1" style="Z-INDEX: 107; 
            LEFT: 448px; POSITION: absolute; TOP: 8px" runat="server" 
            ErrorMessage="Non compreso tra 1 e 10" Width="188px">
            </asp:RangeValidator>

        <asp:RequiredFieldValidator id="RequiredFieldValidator2"
            style="Z-INDEX: 105; LEFT: 448px; POSITION: absolute; TOP: 40px" 
            runat="server" ErrorMessage="Campo vuoto">
            </asp:RequiredFieldValidator>
            
        <asp:RequiredFieldValidator id="RequiredFieldValidator1"
            style="Z-INDEX: 104; LEFT: 448px; POSITION: absolute; TOP: 8px" 
            runat="server" ErrorMessage="Campo vuoto">
            </asp:RequiredFieldValidator>

        ' Sul codice
		
            RequiredFieldValidator1.ControlToValidate = "txtAmpiezza"
            RequiredFieldValidator1.InitialValue = ""

            RequiredFieldValidator2.ControlToValidate = "txtFrequenza"
            RequiredFieldValidator2.InitialValue = ""

            RangeValidator1.ControlToValidate = "txtAmpiezza"
            RangeValidator1.MinimumValue = 1
            RangeValidator1.MaximumValue = 150
            RangeValidator1.Type = ValidationDataType.Integer

            RangeValidator2.ControlToValidate = "txtFrequenza"
            RangeValidator2.MinimumValue = 1
            RangeValidator2.MaximumValue = 10
            RangeValidator2.Type = ValidationDataType.Integer
		
Ultimo aggiornamento 13/02/2004