11. L'applicazione [SimuPaie] – versione 7 – ASP.NET / multi-vista / multi-pagina
Lettura consigliata: riferimento [1], Sviluppo Web con ASP.NET 1.1, sezione: Esempi
Stiamo ora esaminando una versione che è funzionalmente identica all’applicazione ASP.NET a tre livelli [pam-v4-3tier-nhibernate-multivues-monopage] discussa in precedenza, ma ne modifichiamo l’architettura come segue: mentre nella versione precedente le viste erano implementate da una singola pagina ASPX, qui saranno implementate da tre pagine ASPX.
L'architettura dell'applicazione precedente era la seguente:
![]() |
Qui abbiamo un'architettura MVC (Model–View–Controller):
- [Default.aspx.cs] contiene il codice del controller. La pagina [Default.aspx] è l'unico punto di contatto con il client. Gestisce tutte le richieste provenienti dal client.
- [Saisies, Simulation, Simulations, ...] sono le viste. Queste viste sono implementate qui utilizzando i componenti [View] nella pagina [Default.aspx].
L'architettura della nuova versione sarà la seguente:
![]() |
- cambia solo il livello [web]
- le viste (ciò che viene presentato all'utente) rimangono invariate.
- il codice del controller, che nella versione precedente era interamente in [Default.aspx.cs], è ora distribuito su diverse pagine:
- [MasterPage.master]: una pagina che incapsula gli elementi comuni alle diverse viste: il banner superiore con le opzioni di menu
- [Formulaire.aspx]: la pagina che visualizza il modulo di simulazione e gestisce le azioni che avvengono su questo modulo
- [Simulations.aspx]: la pagina che visualizza l'elenco delle simulazioni e gestisce le azioni che avvengono su questa pagina
- [Errors.aspx]: la pagina visualizzata quando si verifica un errore di inizializzazione dell'applicazione. Su questa pagina non è possibile eseguire alcuna azione.
Questa può essere considerata un'architettura MVC multi-controller, mentre l'architettura della versione precedente era un'architettura MVC a controller singolo.
L'elaborazione di una richiesta del client segue questi passaggi:
- Il client invia una richiesta all'applicazione. La richiesta viene indirizzata a una delle due pagine [Formulaire.aspx, Simulations.aspx].
- La pagina richiesta elabora questa richiesta. Per farlo, potrebbe aver bisogno dell'assistenza del livello [business], che a sua volta potrebbe aver bisogno del livello [DAO] se è necessario scambiare dati con il database. L'applicazione riceve una risposta dal livello [business].
- Sulla base di questa risposta, seleziona (3) la vista (= la risposta) da inviare al cliente, fornendogli (4) le informazioni (il modello) di cui ha bisogno.
- La risposta viene inviata al client (5)
11.1. Le viste dell'applicazione
Le diverse schermate visualizzate dall'utente sono le seguenti:
- - la vista [VueSaisies], che visualizza il modulo di simulazione

- - la vista [VueSimulation], utilizzata per visualizzare i risultati dettagliati della simulazione:

- - la vista [SimulationView], che elenca le simulazioni eseguite dal client

- - la vista [EmptySimulationsView], che indica che il client non ha simulazioni o non ne ha più:

- la vista [ErrorView], che indica un errore di inizializzazione dell'applicazione:

11.2. Generazione di viste in un contesto multi-controller
Nella versione precedente, tutte le viste venivano generate dalla singola pagina [Default.aspx]. Questa pagina conteneva due componenti [MultiView] e le viste consistevano in una combinazione di uno o due componenti [View] appartenenti a questi due componenti [MultiView].
Sebbene efficace quando le viste sono poche, questa architettura raggiunge i propri limiti non appena il numero di componenti che formano le varie viste diventa elevato: infatti, ad ogni richiesta effettuata alla singola pagina [Default.aspx], tutti i suoi componenti vengono istanziati, anche se solo alcuni di essi saranno utilizzati per generare la risposta all'utente. Viene quindi eseguito un lavoro superfluo ad ogni nuova richiesta, il che diventa un collo di bottiglia quando il numero totale di componenti sulla pagina è elevato.
Una soluzione consiste nel distribuire le viste su pagine diverse. È ciò che stiamo facendo qui. Esaminiamo due diversi casi di generazione delle viste:
- la richiesta viene effettuata alla pagina P1, che genera la risposta
- la richiesta viene effettuata alla pagina P1, e questa pagina chiede alla pagina P2 di generare la risposta
11.2.1. Caso 1: una pagina controller/vista
Nel Caso 1, torniamo all'architettura a controller singolo della versione precedente, dove la pagina [Default.aspx] è la pagina P1:
![]() |
- il client effettua una richiesta alla pagina P1 (1)
- La pagina P1 elabora questa richiesta. Per farlo, potrebbe aver bisogno dell'assistenza del livello [business] (2), che a sua volta potrebbe aver bisogno del livello [DAO] se è necessario scambiare dati con il database. L'applicazione riceve una risposta dal livello [business].
- Sulla base di questa risposta, seleziona (3) la vista (= la risposta) da inviare al client, fornendogli (4) le informazioni (il modello) di cui ha bisogno. Ciò comporta la selezione dei componenti [Panel] o [View] da visualizzare sulla pagina P1 e l'inizializzazione dei componenti in essi contenuti.
- La risposta viene inviata al client (5)
Ecco due esempi tratti dall'applicazione in esame:
[pagina Formulaire.aspx]
![]() |
- in [1]: dopo aver richiesto la pagina [Formulaire.aspx], l'utente richiede una simulazione
- in [2]: la pagina [Formulaire.aspx] ha elaborato questa richiesta e ha generato la risposta visualizzando un componente [View] che non era stato visualizzato in [1]
[pagina Simulations.aspx]
![]() |
- in [1]: dopo aver richiesto la pagina [Simulations.aspx], l'utente desidera rimuovere una simulazione
- in [2]: la pagina [Simulations.aspx] ha elaborato questa richiesta e ha generato la risposta visualizzando nuovamente il nuovo elenco di simulazioni.
![]() |
11.2.2. Caso 2: una pagina con un singolo controller, una pagina con controller/vista
Il caso 2 può coprire varie architetture. Sceglieremo la seguente:
![]() |
- il client effettua una richiesta alla pagina P1 (1)
- La pagina P1 elabora questa richiesta. Per farlo, potrebbe aver bisogno dell'assistenza del livello [business] (2), che a sua volta potrebbe aver bisogno del livello [DAO] se è necessario scambiare dati con il database. L'applicazione riceve una risposta dal livello [business].
- Sulla base di ciò, seleziona (3) la vista (= la risposta) da inviare al cliente, fornendogli (4) le informazioni (il modello) di cui ha bisogno. In questo caso, la vista da generare deve essere creata da una pagina diversa da P1, in particolare dalla pagina P2. Per eseguire le operazioni (3) e (4), la pagina P1 ha due opzioni:
- trasferire l'esecuzione alla pagina P2 utilizzando l'operazione [Server.Transfer("P2.aspx")]. In questo caso, è possibile inserire il modello destinato alla pagina P2 nel contesto della richiesta [Context.Items["key"]=value] o nella sessione utente [Session.["key"]=value]. La pagina P2 verrà quindi istanziata e, quando viene elaborato il suo evento Load, ad esempio, può recuperare le informazioni passate dalla pagina P1 utilizzando le operazioni [value=(Type)Context.Items["key"] o [value=(Type)Session["key"], a seconda dei casi, dove Type è il tipo del valore associato alla chiave. La trasmissione dei valori tramite il Context è più appropriata se non è necessario che i valori del modello vengano conservati per una futura richiesta del client.
- Chiedere al client di reindirizzarsi alla pagina P2 utilizzando l'operazione [Response.Redirect("P2.aspx")]. In questo caso, la pagina P1 inserirà il modello destinato alla pagina P2 nella sessione, poiché il contesto della richiesta viene cancellato alla fine di ogni richiesta. Tuttavia, in questo caso, il reindirizzamento causerà la fine della prima richiesta del client a P1 e attiverà una seconda richiesta dallo stesso client, questa volta a P2. Ci sono due richieste successive. Sappiamo che la sessione è un modo per preservare la "memoria" tra le richieste. Esistono altre soluzioni oltre alla sessione.
- Indipendentemente da come P2 subentri, torniamo quindi al caso 1: P2 ha ricevuto una richiesta che elaborerà (5) e genererà la risposta autonomamente (6, 7). Possiamo anche immaginare che, dopo aver elaborato la richiesta, la pagina P2 passi il testimone alla pagina P3, e così via.
Ecco un esempio tratto dall'applicazione in esame:
![]() |
- in [1]: l'utente che ha richiesto la pagina [Formulaire.aspx] chiede di visualizzare l'elenco delle simulazioni
- in [2]: la pagina [Formulaire.aspx] elabora questa richiesta e reindirizza il client alla pagina [Simulations.aspx]. È quest'ultima a fornire la risposta all'utente. Invece di chiedere al client di reindirizzarsi, la pagina [Formulaire.aspx] avrebbe potuto inoltrare la richiesta del client alla pagina [Simulations.aspx]. In questo caso in [2], avremmo visto lo stesso URL di [1]. Infatti, un browser visualizza sempre l'ultimo URL richiesto:
- L'azione richiesta in [1] è destinata alla pagina [Formulaire.aspx]. Il browser invia una richiesta POST a questa pagina.
- Se la pagina [Formulaire.aspx] elabora la richiesta e poi la inoltra tramite [Server.Transfer("Simulations.aspx")] alla pagina [Simulations.aspx], rimaniamo all'interno della stessa richiesta. Il browser visualizzerà quindi in [2] l'URL di [Formulaire.aspx] a cui è stato inviato il POST.
- Se la pagina [Formulaire.aspx] elabora la richiesta e poi la reindirizza tramite [Response.Redirect("Simulations.aspx")] alla pagina [Simulations.aspx], il browser effettua una seconda richiesta, una richiesta GET a [Simulations.aspx]. Il browser visualizzerà quindi in [2] l'URL di [Simulations.aspx] a cui è stata inviata la richiesta GET. Questo è ciò che ci mostra la schermata [2] sopra.
11.3. Il progetto Visual Web Developer per il livello [web]
Il progetto Visual Web Developer per il livello [web] è il seguente:
![]() |
- In [1] troviamo:
- il file di configurazione dell'applicazione [Web.config] – che è identico a quello dell'applicazione [pam-v4-3tier-nhibernate-multivues-monopage].
- la pagina [Default.aspx] – reindirizza semplicemente il client alla pagina [Formulaire.aspx]
- la pagina [Formulaire.aspx], che mostra all’utente il modulo di simulazione e gestisce le azioni relative a tale modulo
- la pagina [Simulations.aspx], che mostra all'utente l'elenco delle simulazioni e gestisce le azioni relative a questa pagina
- La pagina [Errors.aspx], che mostra all'utente una pagina che indica un errore riscontrato all'avvio dell'applicazione web.
- In [2] sono riportati i riferimenti del progetto.
Torniamo all'architettura del nuovo progetto:
![]() |
Rispetto al progetto [pam-v4-3tier-nhibernate-multivues-monopage], sono cambiate solo le viste. Ecco perché il nuovo progetto riutilizza alcuni dei file di quel progetto:
- il file di configurazione [Web.config]
- le DLL di riferimento [pam-dao-nhibernate, pam-metier-dao-nhibernate, Spring.Core, NHibernate]
- la classe globale dell'applicazione [Global.asax]
- le cartelle [images, resources, pam]
Per mantenere la coerenza con il progetto attualmente in fase di sviluppo, ci assicureremo che lo spazio dei nomi per le viste e la classe di applicazione globale sia [pam-v7]:
![]() |
11.4. Il codice di presentazione della pagina
11.4.1. La pagina master [MasterPage.master]
Le viste dell'applicazione presentate nella Sezione 11.1 presentano elementi comuni che possono essere raggruppati in una Pagina Master, nota come Master Page in Visual Studio. Prendiamo ad esempio le viste [VueSaisies] e [VueSimulationsVides] riportate di seguito, generate rispettivamente dalle pagine [Formulaire.aspx] e [Simulations.aspx]:
![]() |
Queste due viste condividono il banner superiore (Titolo e Opzioni di menu). Questo vale per tutte le viste che verranno presentate all'utente: avranno tutte lo stesso banner superiore. Per consentire a pagine diverse di condividere lo stesso frammento di presentazione, esistono varie soluzioni, tra cui la seguente:
- Inserire questo frammento comune in un controllo utente. Questa era la tecnica principale in ASP.NET 1.1
- Inserire questo frammento comune in una pagina Master. Questa tecnica è stata introdotta con ASP.NET 2.0. È quella che stiamo utilizzando qui.
Per creare una pagina master in un'applicazione web, procedere come segue:
- Fare clic con il pulsante destro del mouse sul progetto / Aggiungi nuovo elemento / Pagina master:
![]() |
L'aggiunta di una pagina master aggiunge di default tre file all'applicazione web:
- [MasterPage.master]: il codice di layout per la pagina master
- [MasterPage.master.cs]: il codice dei controlli per la pagina master
- [MasterPage.Master.Designer.cs]: le dichiarazioni dei componenti per la pagina master
Il codice generato da Visual Studio in [MasterPage.master] è il seguente:
<%@ Master Language="C#" AutoEventWireup="true" CodeBehind="MasterPage.master.cs" Inherits="pam_v7.MasterPage" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Untitled Page</title>
<asp:ContentPlaceHolder id="head" runat="server">
</asp:ContentPlaceHolder>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:ContentPlaceHolder id="ContentPlaceHolder1" runat="server">
</asp:ContentPlaceHolder>
</div>
</form>
</body>
</html>
- Riga 1: Il tag <%@ Master ... %> viene utilizzato per definire la pagina come pagina master. Il codice di controllo della pagina si troverà nel file specificato dall'attributo CodeBehind, e la pagina erediterà dalla classe specificata dall'attributo Inherits.
- Righe 12–18: Il modulo della pagina master
- Righe 14–16: Un contenitore vuoto che, nella nostra applicazione, conterrà una delle pagine [Form.aspx, Simulations.aspx, Errors.aspx]. Il client riceve sempre la stessa pagina in risposta — la pagina Master — nella quale il contenitore [ContentPlaceHolder1] riceverà un flusso HTML fornito da una delle pagine [Form.aspx, Simulations.aspx, Errors.aspx]. Pertanto, per modificare l'aspetto delle pagine inviate ai client, è sufficiente modificare l'aspetto della pagina Master.
- Righe 8–9: un contenitore vuoto che consente alle pagine "figlie" di personalizzare l'intestazione <head>...</head>.
La rappresentazione visiva (scheda Design) di questo codice sorgente è mostrata in (1) di seguito. Inoltre, è possibile aggiungere tutti i contenitori desiderati utilizzando il componente [ContentPlaceHolder] (2) dalla barra degli strumenti [Standard].
![]() |
Il codice di controllo generato da Visual Studio in [MasterPage.master.cs] è il seguente:
using System;
public partial class MasterPage : System.Web.UI.MasterPage
{
protected void Page_Load(object sender, EventArgs e)
{
}
}
- Riga 3: La classe a cui fa riferimento l'attributo [Inherits] della direttiva <%@ Master ... %> nella pagina [MasterPage.master] deriva dalla classe [System.Web.UI.MasterPage]
Sopra, vediamo la presenza del metodo Page_Load, che gestisce l'evento Load della pagina master. La pagina master conterrà al suo interno un'altra pagina. In quale ordine si verificano gli eventi Load delle due pagine? Questa è una regola generale: l'evento Load di un componente si verifica prima di quello del suo contenitore. Qui, l'evento Load della pagina incorporata nella pagina master si verificherà quindi prima di quello della pagina master stessa.
Per generare una pagina in che utilizzi la precedente pagina [MasterPage.master] come pagina master, è possibile procedere come segue:
![]() |
- in [1]: fare clic con il pulsante destro del mouse sulla pagina master, quindi selezionare [Aggiungi pagina di contenuto]
- in [2]: viene generata una pagina predefinita, in questo caso [WebForm1.aspx].
Il codice di presentazione per [WebForm1.aspx] è il seguente:
<%@ Page Title="" Language="C#" MasterPageFile="~/MasterPage.Master" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="pam_v7.WebForm1" %>
<asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
</asp:Content>
- Riga 1: La direttiva Page e i suoi attributi
- MasterPageFile: specifica il file della pagina master per la pagina descritta dalla direttiva. Il simbolo ~ indica la cartella del progetto.
- Gli altri parametri sono quelli standard per una pagina web ASP
- Righe 2–3: I tag <asp:Content> sono collegati uno per uno alle direttive <asp:ContentPlaceHolder> nella pagina master tramite l'attributo ContentPlaceHolderID. I componenti inseriti tra le righe 2–3 sopra riportate, in fase di esecuzione, saranno inseriti nel contenitore ContentPlaceHolder1 sulla pagina master.
Rinominando la pagina [WebForm1.aspx] generata in questo modo, possiamo creare le varie pagine utilizzando [MasterPage.master] come pagina master.
Per la nostra applicazione [SimuPaie], l'aspetto visivo della pagina master sarà il seguente:
![]() |
N. | Tipo | Nome | Ruolo |
Pannello (in rosa sopra) | intestazione | intestazione della pagina | |
Pannello (giallo sopra) | contenuto | contenuto della pagina | |
Pulsante di collegamento | LinkButtonEseguiSimulazione | richiede il calcolo della simulazione | |
LinkButton | LinkButtonClearSimulation | cancella il modulo di immissione dati | |
LinkButton | LinkButtonVisualizzaSimulazioni | visualizza l'elenco delle simulazioni già eseguite | |
LinkButton | LinkButtonSimulationForm | torna al modulo di immissione dati | |
LinkButton | LinkButtonSalvaSimulazione | salva la simulazione corrente nell'elenco delle simulazioni | |
LinkButton | LinkButtonEndSession | termina la sessione corrente |
Il codice sorgente corrispondente è il seguente:
<%@ Master Language="C#" AutoEventWireup="true" CodeBehind="MasterPage.master.cs" Inherits="pam_v7.MasterPage" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title>Application PAM</title>
</head>
<body background="ressources/standard.jpg">
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server" EnablePartialRendering="true" />
<asp:UpdatePanel runat="server" ID="UpdatePanelPam" UpdateMode="Conditional">
<ContentTemplate>
<asp:Panel ID="entete" runat="server" BackColor="#FFE0C0">
<table>
<tr>
<td>
<h2>
Simulateur de calcul de paie</h2>
</td>
<td>
<label>
 </label>
<asp:UpdateProgress ID="UpdateProgress1" runat="server">
<ProgressTemplate>
<img alt="" src="images/indicator.gif" />
<asp:Label ID="Label5" runat="server" BackColor="#FF8000"
EnableViewState="False" Text="Calcul en cours. Patientez ....">
</asp:Label>
</ProgressTemplate>
</asp:UpdateProgress>
</td>
<td>
<asp:LinkButton ID="LinkButtonFaireSimulation" runat="server"
CausesValidation="False">| Faire la simulation<br />
</asp:LinkButton>
<asp:LinkButton ID="LinkButtonEffacerSimulation" runat="server"
CausesValidation="False">| Effacer la simulation<br />
</asp:LinkButton>
<asp:LinkButton ID="LinkButtonVoirSimulations" runat="server"
CausesValidation="False">| Voir les simulations<br />
</asp:LinkButton>
<asp:LinkButton ID="LinkButtonFormulaireSimulation" runat="server"
CausesValidation="False">| Retour au formulaire de simulation<br />
</asp:LinkButton>
<asp:LinkButton ID="LinkButtonEnregistrerSimulation" runat="server"
CausesValidation="False">| Enregistrer la simulation<br />
</asp:LinkButton>
<asp:LinkButton ID="LinkButtonTerminerSession" runat="server"
CausesValidation="False">| Terminer la session<br />
</asp:LinkButton>
</td>
</tr>
</table>
<hr />
</asp:Panel>
<div>
<asp:Panel ID="contenu" runat="server" BackColor="#FFFFC0">
<asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server">
</asp:ContentPlaceHolder>
</asp:Panel>
</div>
</ContentTemplate>
</asp:UpdatePanel>
</form>
</body>
</html>
- Riga 1: Notare il nome della classe della pagina master: MasterPage
- Riga 8: Definire un'immagine di sfondo per la pagina.
- Righe 9–64: il modulo
- Riga 10: il componente ScriptManager necessario per gli effetti Ajax
- Righe 11–63: il contenitore AJAX
- Righe 12–62: il contenuto abilitato per Ajax
- righe 13–55: il componente Panel [intestazione]
- righe 57-60: il componente Panel [contenuto]
- righe 58–59: il componente [ContentPlaceHolder1], che conterrà la pagina incapsulata [Formulaire.aspx, Simulations.aspx, Erreurs.aspx]
Per creare questa pagina, possiamo inserire nel pannello [header] il codice ASPX della vista [HeaderView] dalla pagina [Default.aspx] della versione [pam-v4-3tier-nhibernate-multivues-monopage], descritta nella sezione 8.5.2.
11.4.2. La pagina [Formulaire.aspx]
Per generare questa pagina, seguire il metodo descritto nella sezione 11.4.1 e rinominare la pagina [WebForm1.aspx] generata in [Form.aspx]. L'aspetto visivo della pagina [Form.aspx] in fase di costruzione sarà il seguente:
![]() |
L'aspetto visivo della pagina [Formulaire.aspx] è costituito da due elementi:
- [1] la pagina master con il suo contenitore [ContentPlaceHolder1] (2)
- [2] i componenti inseriti nel contenitore [ContentPlaceHolder1]. Questi sono identici a quelli dell'applicazione precedente.
Il codice sorgente di questa pagina è il seguente:
<%@ Page Language="C#" MasterPageFile="~/MasterPage.master" AutoEventWireup="true"
CodeBehind="Formulaire.aspx.cs" Inherits="pam_v7.PageFormulaire" Title="Simulation de calcul de paie : formulaire" %>
<%@ MasterType VirtualPath="~/MasterPage.master" %>
<asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" runat="Server">
<div>
<table>
<tr>
<td>
Employé
</td>
<td>
Heures travaillées
</td>
<td>
Jours travaillés
</td>
<td>
</td>
</tr>
...
</asp:Content>
- Riga 1: la direttiva Page con il suo attributo MasterPageFile
- riga 4: la classe di controllo della pagina master può esporre campi e proprietà pubblici. Questi sono accessibili alle pagine incapsulate utilizzando la sintassi Master.[campo] o Master.[proprietà]. La proprietà Master della pagina si riferisce alla pagina master come un'istanza di tipo [System.Web.UI.MasterPage]. Pertanto, nel nostro esempio, dovremmo in realtà scrivere (MasterPage)(Master).[campo] o (MasterPage)(Master).[proprietà]. Questo tipo di conversione può essere evitato inserendo la direttiva MasterType dalla riga 4 nella pagina. L'attributo VirtualPath di questa direttiva specifica il file della pagina master. Il compilatore può quindi riconoscere i campi pubblici, le proprietà e i metodi esposti dalla classe della pagina master, in questo caso di tipo [MasterPage].
- Righe 5–22: il contenuto da inserire nel contenitore [ContentPlaceHolder1] della pagina master.
Questa pagina può essere costruita impostando il suo contenuto (righe 6–21) su quello della vista [VueSaisies] descritta nella Sezione 8.5.3 e su quello della vista [VueSimulation] descritta nella Sezione 8.5.4.
11.4.3. La pagina [Simulations.aspx]
Per generare questa pagina, seguire la procedura descritta nella sezione 11.4.1 e rinominare la pagina [WebForm1.aspx] risultante in [Simulations.aspx]. L'aspetto visivo della pagina [Simulations.aspx] attualmente in fase di costruzione è il seguente:
![]() |
L'aspetto visivo della pagina [Simulations.aspx] è costituito da due elementi:
- [1] la pagina master con il suo contenitore [ContentPlaceHolder1]
- al punto [2] i componenti inseriti nel contenitore [ContentPlaceHolder1]. Questi sono identici a quelli dell'applicazione precedente.
Il codice sorgente di questa pagina è il seguente:
<%@ Page Language="C#" MasterPageFile="~/MasterPage.master" AutoEventWireup="true"
CodeBehind="Simulations.aspx.cs" Inherits="pam_v7.PageSimulations" Title="Pam : liste des simulations" %>
<%@ MasterType VirtualPath="~/MasterPage.master" %>
<asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" runat="Server">
<asp:MultiView ID="MultiView1" runat="server">
<asp:View ID="View1" runat="server">
<h2>
Liste de vos simulations</h2>
<p>
<asp:GridView ID="GridViewSimulations" runat="server" ...>
...
</asp:GridView>
</p>
</asp:View>
<asp:View ID="View2" runat="server">
<h2>
La liste de vos simulations est vide</h2>
</asp:View>
</asp:MultiView><br />
</asp:Content>
Possiamo creare questa pagina impostando il suo contenuto (righe 5–21) su quello della vista [VueSimulations] descritta nella sezione 8.5.5 e su quello della vista [VueSimulationsVides] descritta nella sezione 8.5.6.
11.4.4. La pagina [Errors.aspx]
Per generare questa pagina, seguire la procedura descritta nella sezione 11.4.1 e rinominare la pagina [WebForm1.aspx] risultante in [Errors.aspx]. L'aspetto visivo della pagina [Errors.aspx] attualmente in fase di costruzione è il seguente:
![]() |
L'aspetto visivo della pagina [Errors.aspx] è costituito da due elementi:
- [1] la pagina master con il suo contenitore [ContentPlaceHolder1]
- [2] i componenti inseriti nel contenitore [ContentPlaceHolder1]. Questi sono identici a quelli dell'applicazione precedente.
Il codice sorgente di questa pagina è il seguente:
<%@ Page Language="C#" MasterPageFile="~/MasterPage.master" AutoEventWireup="true"
CodeBehind="Erreurs.aspx.cs" Inherits="pam_v7.PageErreurs" Title="Pam : erreurs" %>
<%@ MasterType VirtualPath="~/MasterPage.master" %>
<asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">
<h3>Les erreurs suivantes se sont produites au démarrage de l'application</h3>
<ul>
<asp:Repeater id="rptErreurs" runat="server">
<ItemTemplate>
<li>
<%# Container.DataItem %>
</li>
</ItemTemplate>
</asp:Repeater>
</ul>
</asp:Content>
11.5. Codice del controllo pagina
11.5.1. Panoramica
Torniamo all'architettura dell'applicazione:
![]() |
- [Global] è l'oggetto [HttpApplication] che inizializza (passaggio 0) l'applicazione. Questa classe è identica a quella della versione precedente.
- Il codice del controller, che nella versione precedente era interamente in [Default.aspx.cs], è ora distribuito su diverse pagine:
- [MasterPage.master]: la pagina master per [Form.aspx, Simulations.aspx, Errors.aspx]. Contiene il menu.
- [Formulaire.aspx]: la pagina che visualizza il modulo di simulazione e gestisce le azioni eseguite su questo modulo
- [Simulations.aspx]: la pagina che visualizza l'elenco delle simulazioni e gestisce le azioni che si verificano su questa pagina
- [Errors.aspx]: la pagina visualizzata quando si verifica un errore di inizializzazione dell'applicazione. Su questa pagina non è possibile eseguire alcuna azione.
L'elaborazione di una richiesta del client segue questi passaggi:
- Il cliente effettua una richiesta all'applicazione. In genere lo fa su una delle due pagine [Form.aspx, Simulations.aspx], ma nulla gli impedisce di richiedere la pagina [Errors.aspx]. È necessario tenere conto di questo scenario.
- La pagina richiesta elabora questa richiesta (fase 1). Per farlo, potrebbe aver bisogno dell'aiuto del livello [business] (fase 2), che a sua volta potrebbe aver bisogno del livello [DAO] se è necessario scambiare dati con il database. L'applicazione riceve una risposta dal livello [business].
- Sulla base di ciò, seleziona (fase 3) la vista (= la risposta) da inviare al client e la fornisce (fase 4) con le informazioni (il modello) di cui ha bisogno. Abbiamo visto tre possibilità per generare questa risposta:
- la pagina richiesta (D) è anche la pagina (R) inviata in risposta. La creazione del modello di risposta (R) consiste quindi nell'assegnare a determinati componenti della pagina (D) i valori che devono avere nella risposta.
- La pagina richiesta (D) non è la pagina (R) inviata in risposta. La pagina (D) può quindi:
- Trasferire il flusso di esecuzione alla pagina (R) utilizzando l'istruzione Server.Transfer(" R "). Il modello può quindi essere inserito nel contesto utilizzando Context.Items("key")=value o, meno comunemente, nella sessione utilizzando Session.Items("key")=value
- Reindirizzare il client alla pagina (R) utilizzando l'istruzione Response.redirect(" R "). Il modello può quindi essere inserito nella sessione ma non nel contesto.
- La risposta viene inviata al client (passaggio 5)
Ciascuna delle pagine [MasterPage.master, Form.aspx, Simulations.aspx, Errors.aspx] risponderà a uno o più dei seguenti eventi:
- Init: primo evento nel ciclo di vita della pagina
- Load: si verifica quando la pagina viene caricata
- Click: un clic su uno dei link nel menu della pagina master
Elaboriamo le pagine una dopo l'altra, a partire dalla pagina master.
11.5.2. Codice di controllo per la pagina [MasterPage.master]
11.5.2.1. Struttura della classe
Il codice di controllo della pagina master ha la seguente struttura:
using System.Web.UI.WebControls;
namespace pam_v7
{
public partial class MasterPage : System.Web.UI.MasterPage
{
// the menu
public LinkButton OptionFaireSimulation
{
get { return LinkButtonFaireSimulation; }
}
...
// set menu
public void SetMenu(bool boolFaireSimulation, bool boolEnregistrerSimulation, bool boolEffacerSimulation, bool boolFormulaireSimulation, bool boolVoirSimulations, bool boolTerminerSession)
{
....
}
// managing the [End session] option
protected void LinkButtonTerminerSession_Click(object sender, System.EventArgs e)
{
....
}
// init master page
protected void Page_Init(object sender, System.EventArgs e)
{
....
}
}
}
}
- riga 5: la classe si chiama [MasterPage] e deriva dalla classe di sistema [System.Web.UI.MasterPage].
- righe 9–14: le 6 opzioni di menu sono esposte come proprietà pubbliche della classe
- righe 16–19: il metodo pubblico SetMenu consente alle pagine [Formulaire.aspx, Simulations.aspx, Erreurs.aspx] di impostare il menu della pagina master
- righe 22–25: la procedura che gestisce il clic sul link [LinkButtonTerminerSession]
- Righe 28–31: la procedura che gestisce l'evento Init della pagina master
11.5.2.2. Proprietà pubbliche della classe
using System.Web.UI.WebControls;
namespace pam_v7
{
public partial class MasterPage : System.Web.UI.MasterPage
{
// the menu
public LinkButton OptionFaireSimulation
{
get { return LinkButtonFaireSimulation; }
}
public LinkButton OptionEffacerSimulation
{
get { return LinkButtonEffacerSimulation; }
}
public LinkButton OptionEnregistrerSimulation
{
get { return LinkButtonEnregistrerSimulation; }
}
public LinkButton OptionVoirSimulations
{
get { return LinkButtonVoirSimulations; }
}
public LinkButton OptionTerminerSession
{
get { return LinkButtonTerminerSession; }
}
public LinkButton OptionFormulaireSimulation
{
get { return LinkButtonFormulaireSimulation; }
}
...
}
}
Per comprendere questo codice, è necessario ricordare i componenti che costituiscono la pagina master:
![]() |
N. | Tipo | Nome | Ruolo |
Pannello (in rosa sopra) | intestazione | intestazione della pagina | |
Pannello (giallo sopra) | contenuto | contenuto della pagina | |
Pulsante di collegamento | LinkButtonEseguiSimulazione | Richiedi calcolo della simulazione | |
LinkButton | LinkButtonClearSimulation | cancella il modulo di immissione dati | |
LinkButton | LinkButtonVisualizzaSimulazioni | visualizza l'elenco delle simulazioni già eseguite | |
LinkButton | LinkButtonSimulationForm | torna al modulo di immissione dati | |
LinkButton | LinkButtonSalvaSimulazione | salva la simulazione corrente nell'elenco delle simulazioni | |
LinkButton | LinkButtonEndSession | termina la sessione corrente |
I componenti da 1 a 6 non sono accessibili al di fuori della pagina che li contiene. Le proprietà nelle righe da 9 a 37 hanno lo scopo di renderli accessibili alle classi esterne, in questo caso alle classi delle altre pagine dell'applicazione.
11.5.2.3. Il metodo SetMenu
Il metodo pubblico SetMenu consente alle pagine [Formulaire.aspx, Simulations.aspx, Erreurs.aspx] di impostare il menu della pagina master. Il suo codice è semplice:
// fixer le menu
public void SetMenu(bool boolFaireSimulation, bool boolEnregistrerSimulation, bool boolEffacerSimulation, bool boolFormulaireSimulation, bool boolVoirSimulations, bool boolTerminerSession)
{
// on fixe les options de menu
LinkButtonFaireSimulation.Visible = boolFaireSimulation;
LinkButtonEnregistrerSimulation.Visible = boolEnregistrerSimulation;
LinkButtonEffacerSimulation.Visible = boolEffacerSimulation;
LinkButtonVoirSimulations.Visible = boolVoirSimulations;
LinkButtonFormulaireSimulation.Visible = boolFormulaireSimulation;
LinkButtonTerminerSession.Visible = boolTerminerSession;
}
11.5.2.4. Gestione degli eventi nella pagina master
La pagina master gestirà due eventi:
- l'evento Init, che è il primo evento nel ciclo di vita della pagina
- l'evento Click sul collegamento [LinkButtonTerminerSession]
La pagina master presenta altri cinque collegamenti: [LinkButtonRunSimulation, LinkButtonSaveSimulation, LinkButtonClearSimulation, LinkButtonViewSimulations, LinkButtonSimulationForm]. A titolo di esempio, esaminiamo cosa occorre fare quando si fa clic sul collegamento [LinkButtonRunSimulation]:
- verificare i dati inseriti (ore, giorni) nella pagina [Form.aspx]
- calcolare lo stipendio
- visualizzare i risultati nella pagina [Form.aspx]
I passaggi 1 e 3 richiedono l'accesso ai componenti presenti nella pagina [Form.aspx]. Ma non è così. Infatti, la pagina master non ha alcuna conoscenza dei componenti presenti nelle pagine che possono essere inserite nel suo contenitore [ContentPlaceHolder1]. Nel nostro esempio, spetta alla pagina [Formulaire.aspx] gestire il clic sul link [LinkButtonFaireSimulation], poiché è la pagina visualizzata quando si verifica questo evento. Come può essere informata di questo evento?
- Poiché il link [LinkButtonFaireSimulation] non fa parte della pagina [Formulaire.aspx], non possiamo scrivere la consueta procedura in [Formulaire.aspx]:
private void LinkButtonFaireSimulation_Click(object sender, System.EventArgs e)
{
...
}
È possibile risolvere il problema utilizzando il seguente codice in [Formulaire.aspx]:
using System.Collections.Generic;
...
namespace pam_v7
{
public partial class Formulaire : System.Web.UI.Page
{
// page loading
protected void Page_Load(object sender, System.EventArgs e)
{
// event manager
Master.OptionFaireSimulation.Click += OptFaireSimulation_Click;
Master.OptionEffacerSimulation.Click += OptEffacerSimulation_Click;
Master.OptionVoirSimulations.Click += OptVoirSimulations_Click;
Master.OptionEnregistrerSimulation.Click += OptEnregistrerSimulation_Click;
...
}
// payroll calculation
private void OptFaireSimulation_Click(object sender, System.EventArgs e)
{
....
}
// delete simulation
private void OptEffacerSimulation_Click(object sender, System.EventArgs e)
{
...
}
protected void OptVoirSimulations_Click(object sender, System.EventArgs e)
{
...
}
protected void OptEnregistrerSimulation_Click(object sender, System.EventArgs e)
{
...
}
}
}
- righe 12–15: Quando si verifica l'evento Load della pagina [Formulaire.aspx], la classe [MasterPage] della pagina master è stata istanziata. Le sue proprietà pubbliche Optionxx sono accessibili e sono di tipo LinkButton, un componente che supporta l'evento Click. Associamo i seguenti metodi a questi eventi Click:
- OptFaireSimulation_Click per l'evento Click sul collegamento LinkButtonFaireSimulation
- OptEffacerSimulation_Click per l'evento Click sul collegamento LinkButtonEffacerSimulation
- OptVoirSimulations_Click per l'evento Click sul collegamento LinkButtonVoirSimulations
- OptEnregistrerSimulation_Click per l'evento Click sul collegamento LinkButtonEnregistrerSimulation
La gestione degli eventi Click sui sei collegamenti del menu sarà distribuita come segue:
- la pagina [Formulaire.aspx] gestirà i collegamenti [LinkButtonRunSimulation, LinkButtonSaveSimulation, LinkButtonClearSimulation, LinkButtonViewSimulations]
- la pagina [Simulations.aspx] gestirà il collegamento [LinkButtonSimulationForm]
- la pagina master [MasterPage.master] gestirà il collegamento [LinkButtonEndSession]. Per questo evento, non è necessario sapere quale pagina incapsula.
11.5.2.5. L'evento Init della pagina master
Le tre pagine [Form.aspx, Simulations.aspx, Errors.aspx] dell'applicazione utilizzano [MasterPage.master] come pagina master. Chiamiamo la pagina master M e la pagina incapsulata E. Quando la pagina E viene richiesta dal client, si verificano i seguenti eventi in ordine:
- E.Init
- M.Init
- E.Load
- M.Load
- ...
Useremo l'evento Init della pagina M per eseguire il codice che deve essere eseguito il prima possibile, indipendentemente dalla pagina di destinazione E. Per identificare questo codice, rivediamo la panoramica dell'applicazione:
![]() |
Sopra, [Global] è l'oggetto [HttpApplication] che inizializza l'applicazione. Questa classe è la stessa della versione [pam-v4-3tier-nhibernate-multivues-monopage]:
using System;
...
namespace pam_v7
{
public class Global : System.Web.HttpApplication
{
// --- static application data ---
public static Employe[] Employes;
public static IPamMetier PamMetier = null;
public static string Msg;
public static bool Erreur = false;
// application startup
public void Application_Start(object sender, EventArgs e)
{
...
}
public void Session_Start(object sender, EventArgs e)
{
...
}
}
}
Se la classe [Global] non riesce a inizializzare correttamente l'applicazione, imposta due variabili pubbliche statiche:
- la variabile booleana Error alla riga 12 viene impostata su true
- la variabile `Msg` alla riga 11 contiene un messaggio che fornisce dettagli sull'errore riscontrato
Quando un utente richiede una delle pagine [Form.aspx, Simulations.aspx] mentre l'applicazione non è stata inizializzata correttamente, tale richiesta deve essere inoltrata o reindirizzata alla pagina [Errors.aspx], che visualizzerà il messaggio di errore proveniente dalla classe [Global]. Esistono diversi modi per gestire questa situazione:
- Eseguire il controllo degli errori di inizializzazione nel gestore di eventi Init o Load di ciascuna delle pagine [Formulaire.aspx, Simulations.aspx]
- Eseguire il controllo degli errori di inizializzazione nel gestore di eventi Init o Load della pagina master per queste due pagine. Questo metodo ha il vantaggio di collocare il controllo degli errori di inizializzazione in un'unica posizione.
Abbiamo scelto di eseguire il controllo degli errori di inizializzazione nel gestore di eventi Init della pagina master:
protected void Page_Init(object sender, System.EventArgs e)
{
// event manager
LinkButtonTerminerSession.Click += LinkButtonTerminerSession_Click;
// initialization errors?
if (Global.Erreur)
{
// is the encapsulated page the error page?
bool isPageErreurs =...;
// if the error page is displayed, leave it alone, otherwise redirect the client to the error page
if (!isPageErreurs)
Response.Redirect("Erreurs.aspx");
return;
}
}
Il codice sopra riportato verrà eseguito non appena verrà richiesta una delle pagine [Form.aspx, Simulations.aspx, Errors.aspx]. Se la pagina richiesta è [Form.aspx] o [Simulations.aspx], reindirizziamo semplicemente (riga 12) il client alla pagina [Errors.aspx], che visualizza il messaggio di errore della classe [Global]. Se la pagina richiesta è [Errors.aspx], questo reindirizzamento non deve avvenire: deve essere visualizzata la pagina [Errors.aspx]. Dobbiamo quindi sapere, all'interno del metodo [Page_Init] della pagina master, quale pagina incapsula.
Rivediamo l'albero dei componenti della pagina master:
...
<body background="ressources/standard.jpg">
<form id="form1" runat="server">
<asp:Panel ID="entete" runat="server" BackColor="#FFE0C0" Width="1239px" >
...
</asp:Panel>
<div>
<asp:Panel ID="contenu" runat="server" BackColor="#FFFFC0">
<asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server">
</asp:ContentPlaceHolder>
</asp:Panel>
</div>
</form>
</body>
</html>
- righe 1-13: il contenitore con id "form1"
- righe 4-6: il contenitore con ID "entete", incluso nel contenitore con ID "form1"
- righe 8-11: il contenitore con id "content", incluso nel contenitore con id "form1"
- righe 9-10: il contenitore con id "ContentPlaceHolder1", incluso nel contenitore con id "content"
Una pagina E incorporata nella pagina master M è contenuta all'interno del contenitore con id "ContentPlaceHolder1". Per fare riferimento a un componente con id C su questa pagina E, scriveremmo:
this.FindControl("form1").FindControl("contenu").FindControl("ContentPlaceHolder1").FindControl("C");
L'albero dei componenti per la pagina [Errors.aspx] è il seguente:
<%@ Page Language="C#" MasterPageFile="~/MasterPage.master" AutoEventWireup="true"
CodeBehind="Erreurs.aspx.cs" Inherits="pam_v7.PageErreurs" Title="Pam : erreurs" %>
<%@ MasterType VirtualPath="~/MasterPage.master" %>
<asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">
<h3>Les erreurs suivantes se sont produites au démarrage de l'application</h3>
<ul>
<asp:Repeater id="rptErreurs" runat="server">
<ItemTemplate>
<li>
<%# Container.DataItem %>
</li>
</ItemTemplate>
</asp:Repeater>
</ul>
</asp:Content>
Quando la pagina [Errors.aspx] viene unita alla pagina master M, il contenuto del tag <asp:Content> sopra riportato (righe 5–16) viene integrato nel tag <asp:ContentPlaceHolder> con l'ID "ContentPlaceholder1" nella pagina M, generando la seguente struttura ad albero dei componenti:
- Riga 12: Il componente [rptErrors] può essere utilizzato per determinare se la pagina master M contiene o meno la pagina [Errors.aspx]. Questo componente è presente solo in questa pagina.
Queste spiegazioni sono sufficienti per comprendere il codice della procedura [Page_Init] nella pagina master:
protected void Page_Init(object sender, System.EventArgs e)
{
// event manager
LinkButtonTerminerSession.Click += LinkButtonTerminerSession_Click;
// initialization errors?
if (Global.Erreur)
{
// is the encapsulated page the error page?
bool isPageErreurs = this.FindControl("form1").FindControl("contenu").FindControl("ContentPlaceHolder1").FindControl("rptErreurs") != null;
// if the error page is displayed, leave it alone, otherwise redirect the client to the error page
if (!isPageErreurs)
Response.Redirect("Erreurs.aspx");
return;
}
}
- Riga 4: associamo un gestore di eventi all'evento Click sul collegamento LinkButtonTerminerSession. Questo gestore si trova nella classe MasterPage.
- Riga 6: Verifichiamo se la classe [Global] ha impostato il suo valore booleano Error
- riga 9: in tal caso, il valore booleano IsPageErrors indica se la pagina incapsulata nella pagina master è la pagina [Errors.aspx]
- riga 12: se la pagina incapsulata nella pagina master non è la pagina [Errors.aspx], il client viene reindirizzato a quella pagina; altrimenti, non viene eseguita alcuna operazione.
11.5.2.6. L'evento Click sul collegamento [LinkButtonTerminerSession]
![]() |
Quando l'utente fa clic sul collegamento [End Session] nella vista (1) sopra, la sessione deve essere svuotata dei suoi contenuti e deve essere visualizzato un modulo vuoto (2).
Il codice per il gestore di questo evento potrebbe essere il seguente:
protected void LinkButtonTerminerSession_Click(object sender, System.EventArgs e)
{
// quit session
Session.Abandon();
// the [form] view is displayed
Response.Redirect("Formulaire.aspx");
}
- Riga 4: la sessione corrente viene interrotta
- riga 6: il client viene reindirizzato alla pagina [Form.aspx]
Possiamo notare che questo codice non coinvolge nessuno dei componenti delle pagine [Form.aspx, Simulations.aspx, Errors.aspx]. L'evento può quindi essere gestito dalla pagina master stessa.
11.5.3. Codice di controllo per la pagina [Errors.aspx]
Il codice di controllo per la pagina [Errors.aspx] potrebbe essere il seguente:
using System.Collections.Generic;
namespace pam_v7
{
public partial class Erreurs : System.Web.UI.Page
{
protected void Page_Load(object sender, System.EventArgs e)
{
// initialization errors?
if (Global.Erreur)
{
// prepare the template for the [errors] page
List<string> erreursInitialisation = new List<string>();
erreursInitialisation.Add(Global.Msg);
// associate the error list with its component
rptErreurs.DataSource = erreursInitialisation;
rptErreurs.DataBind();
}
// set the menu
Master.SetMenu(false, false, false, false, false, false);
}
}
}
Ricordate che la pagina [Errors.aspx] ha il solo scopo di visualizzare un errore di inizializzazione dell'applicazione quando se ne verifica uno:
- riga 10: verifichiamo se l'inizializzazione si è conclusa con un errore
- righe 13–14: in tal caso, il messaggio di errore (Global.Msg) viene inserito in un elenco [InitializationErrors]
- righe 16-17: al componente [rptErrors] viene richiesto di visualizzare questo elenco
- riga 20: in tutti i casi (errore o meno), le opzioni del menu della pagina master non vengono visualizzate, quindi l'utente non può avviare alcuna nuova azione da questa pagina.
Cosa succede se l'utente richiede direttamente la pagina [Errors.aspx] (cosa che non dovrebbe fare durante il normale utilizzo dell'applicazione)? Esaminando il codice in [MasterPage.master.cs] e [Errors.aspx.cs], vedremo che:
- se si è verificato un errore di inizializzazione, questo viene visualizzato
- se non c'è stato alcun errore di inizializzazione, l'utente riceve una pagina contenente solo l'intestazione da [MasterPage.master] senza alcuna opzione di menu visualizzata.
11.5.4. Codice di controllo per la pagina [Formulaire.aspx]
11.5.4.1. Struttura della classe
Lo scheletro del codice di controllo per la pagina [Form.aspx] potrebbe essere il seguente:
using Pam.Metier.Entites;
...
partial class PageFormulaire : System.Web.UI.Page
{
// page loading
protected void Page_Load(object sender, System.EventArgs e)
{
// event manager
Master.OptionFaireSimulation.Click += OptFaireSimulation_Click;
Master.OptionEffacerSimulation.Click += OptEffacerSimulation_Click;
Master.OptionVoirSimulations.Click += OptVoirSimulations_Click;
Master.OptionEnregistrerSimulation.Click += OptEnregistrerSimulation_Click;
....
}
// payroll calculation
private void OptFaireSimulation_Click(object sender, System.EventArgs e)
{
....
}
// delete simulation
private void OptEffacerSimulation_Click(object sender, System.EventArgs e)
{
...
}
protected void OptVoirSimulations_Click(object sender, System.EventArgs e)
{
....
}
protected void OptEnregistrerSimulation_Click(object sender, System.EventArgs e)
{
...
}
}
Il codice di controllo della pagina [Formulaire.aspx] gestisce cinque eventi:
- l'evento Load della pagina
- l'evento Click sul collegamento [LinkButtonRunSimulation] nella pagina master
- l'evento Click sul collegamento [LinkButtonClearSimulation] nella pagina master
- l'evento Click sul collegamento [LinkButtonEnregistrerSimulation] nella pagina master
- l'evento Click sul collegamento [LinkButtonViewSimulations] nella pagina master
11.5.4.2. Evento Page Load
Lo scheletro del gestore dell'evento Load della pagina potrebbe essere il seguente:
protected void Page_Load(object sender, System.EventArgs e)
{
// event manager
Master.OptionFaireSimulation.Click += OptFaireSimulation_Click;
Master.OptionEffacerSimulation.Click += OptEffacerSimulation_Click;
Master.OptionVoirSimulations.Click += OptVoirSimulations_Click;
Master.OptionEnregistrerSimulation.Click += OptEnregistrerSimulation_Click;
// view [entries] display
...
// menu positioning master page
...
// query processing GET
if (!IsPostBack)
{
// loading employee names into the combo
...
// init view [entries] with entries stored in the session if they exist
....
}
}
Un esempio per chiarire il commento alla riga 17 potrebbe essere questo:
![]() |
![]() |
- In [1], chiediamo di vedere l'elenco delle simulazioni. Sono state inserite voci in [A, B, C].
- In [2], visualizziamo l'elenco
- In [3], chiediamo di tornare al modulo
- in [4], il modulo viene visualizzato esattamente come era stato lasciato. Poiché c'erano due richieste, (1,2) e (3,4), ciò significa che:
- passando da [1] a [2], le voci di [1] sono state salvate
- quando si passa da [3] a [4], sono state ripristinate. È la procedura [Page_Load] in [Form.aspx] che esegue questo ripristino.
Domanda: Completa la procedura Page_Load utilizzando i commenti e il codice della versione [pam-v4-3tier-nhibernate-multivues-monopage]
11.5.4.3. Gestione degli eventi Click sui link del menu
Lo scheletro dei gestori di eventi Click per i collegamenti nella pagina master è il seguente:
// payroll calculation
private void OptFaireSimulation_Click(object sender, System.EventArgs e)
{
// ajax effect
Thread.Sleep(3000);
// valid page?
Page.Validate();
if (!Page.IsValid)
{
// view display [input]
...
}
// the page is validated - inputs are retrieved
...
// we calculate the employee's salary
FeuilleSalaire feuillesalaire;
try
{
feuillesalaire = ...;
}
catch (PamException ex)
{
// we encountered a problem
...
return;
}
// put the result in the session
Session["simulation"] = ...;
// put the entries in the session
...
// display
...
// views display
...
// display menu MasterPage
...
}
// delete simulation
private void OptEffacerSimulation_Click(object sender, System.EventArgs e)
{
// display panel [input]
...
// selection 1st employee
...
}
protected void OptVoirSimulations_Click(object sender, System.EventArgs e)
{
// put the entries in the session
...
// the [simulations] view is displayed
Response.Redirect("simulations.aspx");
}
protected void OptEnregistrerSimulation_Click(object sender, System.EventArgs e)
{
// save the current simulation in the user's session
...
// the [simulations] view is displayed
Response.Redirect("simulations.aspx");
}
Domanda: Completa il codice per le procedure sopra riportate utilizzando i commenti e il codice della versione [pam-v4-3tier-nhibernate-multivues-monopage]
11.5.5. Codice di controllo per la pagina [Simulations.aspx]
Lo scheletro del codice di controllo per la pagina [Simulations.aspx] potrebbe essere il seguente:
using System.Collections.Generic;
using Pam.Web;
using System.Web.UI.WebControls;
partial class PageSimulations : System.Web.UI.Page
{
// simulations
private List<Simulation> simulations;
// page loading
protected void Page_Load(object sender, System.EventArgs e)
{
// event manager
Master.OptionFormulaireSimulation.Click += OptFormulaireSimulation_Click;
GridViewSimulations.RowDeleting += GridViewSimulations_RowDeleting;
// simulations are retrieved from the
simulations = ...;
// are there any simulations?
if (simulations.Count != 0)
{
// first view visible
...
// fill the gridview
...
}
else
{
// second view
...
}
// set the menu
...
}
protected void GridViewSimulations_RowDeleting(object sender, System.Web.UI.WebControls.GridViewDeleteEventArgs e)
{
// simulations are retrieved from the
List<Simulation> simulations = ...;
// delete the designated simulation (e.RowIndex represents the number of the deleted line in the gridview)
..
// are there any simulations left?
if (simulations.Count != 0)
{
// fill the gridview
...
}
else
{
// view [SimulationsVides]
...
}
}
protected void OptFormulaireSimulation_Click(object sender, System.EventArgs e)
{
// the [form] view is displayed
Response.Redirect("formulaire.aspx");
}
}
Domanda: Completa il codice per le procedure sopra riportate utilizzando i commenti e il codice della versione [pam-v4-3tier-nhibernate-multivues-monopage]
11.5.6. Codice di controllo per la pagina [Default.aspx]
È possibile includere una pagina [Default.aspx] nell'applicazione per consentire all'utente di richiedere l'URL dell'applicazione senza specificare una pagina, come mostrato di seguito:
![]() |
La richiesta [1] ha ricevuto in risposta la pagina [Formulaire.aspx] (2). Sappiamo che la richiesta (1) viene gestita per impostazione predefinita dalla pagina [Default.aspx] dell'applicazione. Per ottenere (2), [Default.aspx] deve semplicemente reindirizzare il client alla pagina [Formulaire.aspx]. Ciò può essere ottenuto con il seguente codice:
partial class _Default : System.Web.UI.Page
{
protected void Page_Init(object sender, System.EventArgs e)
{
// redirects to the input form
Response.Redirect("Formulaire.aspx");
}
}
La pagina di presentazione [Default.aspx] contiene solo la direttiva che la collega a [Default.aspx.cs]:
<%@ Page Language="C#" AutoEventWireup="true"
CodeBehind="Default.aspx.cs" Inherits="pam_v7._Default" Title="Untitled Page" %>

























