Affrontiamo il problema visto nella lezione precedente, stavolta con C#. Mentre con PHP il report è una chiamata a fine codice, con C# è necessario catturare fin da subito l'eventuale output e, potendolo salvare in un file di testo, evitiamo di separare risposta e richiesta ed accorpiamo il tutto un unico file richiamando un metodo, CreaReport()
, subito dopo aver istanziato la classe.
Dichiariamo il namespace AJAX
e creiamo due classi: InformazioniAjax
, FiltroRisposta
. Come di consueto i commenti nel codice ne chiariranno il funzionamento.
Listato 26. Namespace per il debug di AJAX
namespace AJAX
{
// classe InformazioniAjax,
// gestisce i dati di ingresso della pagina
// ed il filtro per creare un report testuale.
public class InformazioniAjax
{
// variabile privata tipo stringa contenente l'output
private System.String __inizioReport;
// variabile privata di assegnazione Response
private System.Web.HttpResponse __risposta;
// costruttore, memorizza il response e crea la stringa
// con il dump delle variabili inviate in GET o POST
public InformazioniAjax(System.Web.HttpRequest richiesta, System.Web.HttpResponse risposta)
{
__risposta = risposta;
__inizioReport = "REPORT DEL " + System.DateTime.Now.ToString() + "rnrn" + "[VARIABILI GET]rn" + this.__Dump(richiesta.QueryString) + "rn" + "---------------------------------rnrn" + "[VARIABILI POST]rn" + this.__Dump(richiesta.Form) + "rn" + "_________________________________rnrn" + "[OUTPUT GENERATO]rn";
}
// inizializza la variabile da usare come filtro, creata tramite la classe
// FiltroRisposta, aggiunge a inizio file le informazioni GET e POST della
// variabile __inizioReport ed assegna il filtro alla pagina. Accetta il nome
// del file sul quale salvare le informazioni.
public void CreaReport(System.String fileReport)
{
FiltroRisposta fr = new FiltroRisposta(__risposta.Filter, ref fileReport);
// prima di assegnare il filtro, scrivo il report sulla Request
// effettuato nel costruttore ed assegnato a __inizioReport
fr.ScriviInizioReport(ref __inizioReport);
// ora è possibile assegnare il filtro
__risposta.Filter = fr;
}
// overload del metodo CreaReport, se non viene
// specificata la stringa crea il file report nella cartella App_Data
// ovvero dove si dovrebbe trovare questo stesso file
public void CreaReport()
{
this.CreaReport(System.AppDomain.CurrentDomain.BaseDirectory + "\App_Data\report.txt");
}
// metodo privato, crea una stringa contenente le coppie
// chiave/valore per il tipo di richiesta e la restituisce
private System.String __Dump(System.Collections.Specialized.NameValueCollection richiesta)
{
System.String risultato = "";
System.String[] chiavi = richiesta.AllKeys;
for (System.Int32 a = 0; a < chiavi.Length; a++)
risultato += chiavi[a] + "rnt" + richiesta.Get(chiavi[a]) + "rn";
return risultato;
}
}
// classe FiltroRisposta, estende la classe System.IO.Stream
// crea un file di testo contenente i dati inviati al client
// se assegnata come filtro.
// (versione riadattata del codice presente in questa pagina)
public class FiltroRisposta : System.IO.Stream
{
// output mostrato al client
private System.IO.Stream __browser;
// posizione stringa
private System.Int64 __posizione;
// file dove aggiungere le informazioni
// testuali mostrate al client (output testuale)
private System.IO.FileStream __fileReport;
// costruttore pubblico,
// accetta uno stream, in questo caso il Filter della Response
// ed il nome del file per riferimento sulla quale effettuare il report
public FiltroRisposta(System.IO.Stream browser, ref System.String fileReport)
{
__browser = browser;
__fileReport = new System.IO.FileStream(fileReport, System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.Write);
}
// scrive una stringa sul file di report, in questo caso la variabile
// inizioReport inviata per riferimento dal gestore
//(vedere la classe InformazioniAjax ed il metodo CreaReport)
public void ScriviInizioReport(ref System.String inizioReport)
{
System.Byte[] buffer = System.Text.Encoding.Default.GetBytes(inizioReport);
__fileReport.Write(buffer, 0, inizioReport.Length);
}
// override di un metodo pubblico,
// invia l'output al browser e scrive lo stesso nel file inviato al costruttore
public override void Write(System.Byte[] buffer, System.Int32 offset, System.Int32 count)
{
__browser.Write(buffer, 0, count);
__fileReport.Write(buffer, 0, count);
}
// lista di metodi pubblici sulla quale effettuare l'override
// per scavalcare i controlli standard sul flusso dati in uscita
public override System.Boolean CanRead { get { return true; } }
public override System.Boolean CanSeek { get { return false; } }
public override System.Boolean CanWrite { get { return false; } }
public override System.Int64 Length { get { return 0; } }
public override long Seek(System.Int64 offset, System.IO.SeekOrigin direction) { return 0; }
public override void SetLength(System.Int64 length) { __browser.SetLength(length); }
public override void Flush() { __browser.Flush(); }
public override int Read(System.Byte[] buffer, System.Int32 offset, System.Int32 count) { return __browser.Read(buffer, offset, count); }
public override System.Int64 Position { get { return __posizione; } set { __posizione = value; } }
public override void Close() {
__browser.Close();
__fileReport.Close();
}
}
}
La scelta di non usare using
è voluta, lo scopo è quello di capire al meglio da cosa derivano tutte le classi utilizzate.
Seppure possa non essere ottimizzato al massimo, il codice è molto simile a quello proposto per PHP e potrebbe essere utile anche per capire alcune differenze sostanziali tra i due linguaggi.
Chiusa la parentesi sui confronti e sulla classe, ecco un esempio di cosa scrivere in un file che vorrebbe sfruttarla.
Listato 27. Esempio di uso della classe InformazioniAjax
<%@ Page Language="C#" Debug="true" %>
<%@ Assembly Src="App_Data/InformazioniAjax.class.cs" %>
<script runat="server" Language="C#">
// file Default.aspx,
// a differenza di PHP, sia l'istanza della classe sia il metodo di creazione
// report devono essere effettuati subito all'interno del metodo OnInit
override protected void OnInit(System.EventArgs e) {
AJAX.InformazioniAjax ajaxInfo = new AJAX.InformazioniAjax(Request, Response);
ajaxInfo.CreaReport();
// eventuali altre operazioni ...
}
// a questo punto è possibile inviare la pagina
// o scrivere qualcosa nel metodo Load
void Page_Load() {
// stampa dati di qualunque tipo, in questo
// caso una semplice stringa, un link ed una form
Response.Write(@"Verifica del funzionamento del file di report<br /> <a href=""?variabile=valore"">prova una richiesta in get</a><br /> <form action=""?altravar=altrovalore"" method=""post""> <input type=""submit"" name=""form"" value=""invio dati in post"" /> </form>");
}
</script>
Salvando quest'ultimo file come Default.aspx
e salvando la classe come InformazioniAjax.class.cs
all'interno della cartella App_Data
, è possibile testare questa pagina che è identica in tutto e per tutto a quella mostrata per il PHP. Una scritta, un link ed un form, non resta che assegnare permessi di scrittura alla cartella App_Data
ed andare a leggere, dopo aver richiamato la pagina o cliccato su uno dei suoi elementi, il contenuto del file report.txt
.
È possibile scaricare il codice ASP.NET proposto per testarlo direttamente sulle nostre macchine. Come è già stato detto, entrambe le proposte servono come spunto e per essere riadattate ad esigenze particolari.