Sono stati pubblicati su HTML.it due miei nuovi articoli che trattano in modo approfondito la scrittura di provider personalizzati, prendendo come database di esempio SQLite:
Fatemi sapere cosa ne pensate! :)
Sono stati pubblicati su HTML.it due miei nuovi articoli che trattano in modo approfondito la scrittura di provider personalizzati, prendendo come database di esempio SQLite:
Fatemi sapere cosa ne pensate! :)
Voglio segnalare alcuni articoli che ho trovato molto interessanti.
Infine vorrei segnalare un progetto che mi era rimasto sconosciuto fino ad oggi: Volta, che si propone di unificare lo sviluppo lato server e client semplificando non poco la vita a noi poveri sviluppatori.
E’ online su HTML.it un mio articolo dedicato a ASP.Net & SQLite che, oltre all’interazione fra le due tecnologie, offre una sostanziosa introduzione al motore di database e alle sue particolarità, soprattutto in confronto ai database tradizionali.
Penso che verrà presto pubblicato anche un altro articolo che ho scritto sempre per HTML.it, dedicato ancora una volta a SQLite e in particolare alla creazione, spiegata molto dettagliatamente, di un MembershipProvider personalizzato.
Come probabilmente saprete, i provider vengono caricati in memoria, attraverso l’utilizzo di classi statiche, all’avvio dell’applicazione web. Proprio perchè il loro ciclo di vita dipende strettamente da quello dell’applicazione, è impossibile modificarne le proprietà, come ad esempio la stringa di connessione al database.
Ma perchè doverla modificare? Un esempio potrebbe essere quello che segue.
Abbiamo la necessità di definire due diverse strighe di connessione, una per l’ambiente di sviluppo e l’altra per quello di produzione. Generalmente esse verranno salvate all’interno del file web.config nella sezione connectionStrings:
<connectionStrings>
<!-- Sviluppo -->
<add name="DebugConnString" connectionString="Data Source=ServerSviluppo;Initial Catalog=MioDatabase;" providerName="System.Data.SqlClient"/>
<!-- Produzione -->
<add name="ProductionConnString" connectionString="Data Source=ServerProduzione;Initial Catalog=MioDatabase;" providerName="System.Data.SqlClient"/>
</connectionStrings>
E potrebbero essere utilizzate, ad esempio, per un Membership Provider:
<membership defaultProvider="SqlProvider" userIsOnlineTimeWindow="30">
<providers>
<clear />
<add
name="SqlProvider"
type="System.Web.Security.SqlMembershipProvider"
connectionStringName="DebugConnString"
applicationName="MiaApplicazione"
enablePasswordRetrieval="false"
enablePasswordReset="true"
requiresQuestionAndAnswer="true"
requiresUniqueEmail="true"
passwordFormat="Hashed" />
</providers>
</membership>
Passando da un ambiente all’altro ci troviamo quindi a dover modificare manualmente il file web.config per selezionare la stringa di connessione necessaria, senza pensare ai problemi che potrebbero derivare da una eventuale dimenticanza.
La soluzione a questi problemi consiste nell’utilizzo della Reflection, che ci consente di andare a modificare le variabili di una classe, anche quando queste sono state dichiarate private. Il codice che segue va aggiunto al file Global.asax:
<%@ Application Language="C#" %>
<%@ Import Namespace="System.Reflection" %>
<%@ Import Namespace="System.Configuration" %>
<script runat="server">
void Application_Start(object sender, EventArgs e)
{
// Cerco il provider
MembershipProvider mp = Membership.Provider;
Type t = mp.GetType();
// Cerco la variabile privata _sqlConnectionString all'interno dell'istanza
// del provider
FieldInfo info = t.GetField("_sqlConnectionString", BindingFlags.Instance | BindingFlags.IgnoreCase | BindingFlags.NonPublic);
// La modifico a seconda di quella che ci serve
// Soltanto il codice necessario verrà effettivamente compilato
#if DEBUG
// Siamo in sviluppo
info.SetValue(mp,
ConfigurationManager.ConnectionStrings["DebugConnString"].ConnectionString);
#else
// Siamo in produzione
info.SetValue(mp,
ConfigurationManager.ConnectionStrings["ProductionConnString"].ConnectionString);
#endif
}
</script>
Anche se è da considerarsi più un “trucco” che una pratica di programmazione corretta, questo sistema funziona e può tornare utile in molte situazioni.
Ho appena letto una notizia, a cui rimando per ulteriori informazioni e commenti, su Punto Informatico che è a metà tra il preoccupante e il grottesco.
L’argomento è la Internet Tax, un provvedimento varato dal Governo in tema di editoria. Cosa prevede? E’ presto detto: qualsiasi attività web dovrà registrarsi al ROC
(Registro degli operatori di Comunicazione).
Il primo impatto di una normativa del genere sarà la chiusura della maggior parte dei blog e dei siti di informazione che pubblicano materiale editoriale, sia con cadenza regolare (ad es. quotidianamente) che irregolare (un testo ogni tanto), facendo di fatto retrocedere la rete italiana ad un livello medioevale. Oltre ad impoverire la cultura libera che circola ormai da anni sulla rete, un decreto come questo colpirà duramente il mercato interno relativo a servizi di hosting, innescando la "fuga", dettata dalle leggi della sopravvivenza, dei nostri siti internet all’estero.
Ma la cosa che più colpisce è la motivazione per cui il provvedimento è stato presentato: difendere dalla diffamazione. Ovviamente questa non è che la facciata di una manovra che porterebbe nelle tasche dell’erario non pochi soldi e consentirebbe ai nostri cari politici di poter evitare di confrontarsi con le molte critiche e provocazioni che ogni giorno piovono loro addosso da internet.
Poveretti, come non capirli? Effettivamente ammettere (senza quindi far polemica) i propri errori quando te li fanno notare non è lavoro da poco (Mastella mi senti?), soprattutto per chi ha un compito modesto come quello di guidare un’intera nazione. Compito modesto, direi, quanto il loro stipendio e la loro età media.
La soluzione, quindi, per non dover rendere conto a nessuno è sempre la solita, vecchia ma funzionale: la censura. Ed è proprio quello che stanno cercando di attuare piano piano sia con questa proposta, che con altre precedenti (chi si ricorda la legge Urbani?) e, magari, con altre future.
Quello che comunque è chiaro e sotto gli occhi di tutti è come i nostri politici, senza distinzioni di partito o ideologia, abbiano fatto il loro tempo e assomiglino sempre più a dinosauri in una cristalleria, lontani oramai non solo dalle esigenze quotidiane (on-line e non) dei cittadini, ma anche da quel minimo di decenza ed umiltà necessarie per ricoprire cariche così importanti.
Dopo circa un giorno di gioco al demo di Unreal Tournament 3 (rilasciato ieri e scaricaribile dai maggiori siti di videogame, nonchè come torrent da molti tracker), ecco le mie prime considerazioni:
L’installazione infatti non era stata testata con questi sistemi operativi e, soltanto sopo molte segnalazioni (a cui inizialmente sono arrivate risposte abbastanza confuse e sorprese da parte di Epic), è stato fornito un primo workaround per installare il gioco, che tuttavia si rifiutava di partire! Ecco quindi il secondo workaround per risolvere il problema e cominciare finalmente a giocare!
La prima domanda che, credo, verrà spontanea anche a voi sarà: per quale arcano motivo devo effettuare un login? E soprattutto come mai questo sistema di autenticazione è basato su (l’odioso) GameSpy (il network a cui appartiene FilePlanet), tra l’altro senza che questo sia scritto da nessuna parte? UT 3, ho scoperto dopo, utilizza GameSpy per gestire l’identità che il giocatore avrà on-line, che tradotto significa: o ti registri o non giochi. E, a proposito di registrazione, mi spiace segnalare che la procedura, invece di essere scontata, è resa frustrante dai messaggi di errore imprecisi e poco accurati che vengono presentati in caso di inserimento di dati non corretti.
E’ vero che per chi non desidera giocare on-line è disponibile una modalità off-line, ma l’accesso a questa seconda modalità non è troppo intuitivo come avrebbe dovuto essere. Ancora una volta Epic non ci siamo.
Comunque, una volta superata la pagina di accesso, il menu principale non è niente male: il logo di UT 3 sulla sinistra, la lista delle azioni sulla destra e come sottofondo un riadattamento della vecchia colonna sonora di UT, woooow! Le impostazioni sono ben accessibili e molto semplici. Forse anche troppo. Per cambiarle in modo più approfondito sono dovuto andare a modificare manualmente i files di configurazione, che sono salvati qui: C:\Documents and Settings\nome_utente\My Documents\My Games\Unreal Tournament 3 Demo\UTGame\Config .
Dopo aver messo tutti i dettagli al massimo per verificare le prestazioni (argomento trattato nella prossima sezione), selezionando Instant Action ho dato il via ad un Cattura la Bandiera con Veicoli nell’unica mappa disponibile nel demo: Suspense.
Ora se volete scusarmi torno a giocare! :)
Preso direttamente da un post di Mark Rein sul forum di Epic Games:
Just wanted to give you a heads’ up that we’re getting pretty close to releasing the Unreal Tournament 3 Beta Demo for Windows. The Beta Demo will allow instant action play against bots as well as online multiplayer. The purpose of the Beta Demo is to test the game on a large variety of hardware configurations and get gameplay feedback from the community. The development team feels they’re pretty close to being ready to release this so it could come out this week but for safety sake I’d say it should be out within two weeks.
Quindi soltanto due settimane al demo! :D
Negli interventi precedenti sono stati trattati, dopo una rapida introduzione a SQLite, la creazione del database e della pagina di amministrazione.
In questo ultimo intervento vedremo, invece, come creare l’ultimo componente del mini-blog: una semplice pagina per visualizzare gli interventi e navigarli per categorie.
La struttura sarà molto simile a quella della pagina di amministrazione: tramite una MultiView, infatti, caricheremo o una lista degli ultimi dieci interventi, oppure una lista degli interventi appartenenti ad una determinata categoria.
Il layout sarà costituito da due colonne, quella di sinistra conterrà il menu di navigazione e l’altra gli interventi:
<div style="width:75%;">
<div style="float: left; width: 25%;"></div>
<div style="float: right; width: 69%;"></div>
</div>
Per mostrare la lista delle categorie, sarà sufficiente un controllo Repeater associato ad un SqlDataSource (per la quanto riguarda la creazione della stringa di connessione al database si veda la seconda parte del tutorial):
<div style="float: left; width: 25%;">
<span style="font-weight: bold;">Categorie</span>
<asp:Repeater ID="Categorie" runat="server" DataSourceID="Categorie_Source">
<HeaderTemplate>
<ul>
</HeaderTemplate>
<ItemTemplate>
<li>
<a href="default.aspx?categoria=<%# (string)Eval("NomeCategoria") %>"
title="<%# (string)Eval("NomeCategoria") %>">
<%# (string)Eval("NomeCategoria") %></a>
</li>
</ItemTemplate>
<FooterTemplate>
</ul>
</FooterTemplate>
</asp:Repeater>
</div>
<asp:SqlDataSource ID="Categorie_Source" runat="server" ProviderName="System.Data.SQLite"
ConnectionString="<%$ ConnectionStrings:ExampleBlogConnString %>"
SelectCommand="SELECT * FROM Categorie">
</asp:SqlDataSource>
Come potete vedere il Repeater crea una lista non ordinata di elementi che nel nostro caso saranno i nomi delle categorie, con un link che passa come parametro nella query string il nome della categoria. Questo viene recuperato nell’evento onLoad della pagina e la vista attiva all’interno del MultiView (che creeremo fra poche righe) modificata di conseguenza:
protected void Page_Load(object sender, EventArgs e)
{
if (!this.IsPostBack)
if (!string.IsNullOrEmpty(Request.QueryString["categoria"]))
{
MultiView1.ActiveViewIndex = 1;
NomeCategoria.Text = Request.QueryString["categoria"];
}
else
MultiView1.ActiveViewIndex = 0;
}
Ecco qui, per concludere il controllo MultiView incaricato di mostrare gli interventi. Il codice mi sembra abbastanza semplice da non richiedere ulteriore analisi, per ogni dubbio lasciate un commento!
<asp:MultiView id="MultiView1" runat="server" activeviewindex="0">
<asp:View ID="ListaInterventi" runat="server">
<h1>Ultimi Interventi</h1>
<asp:Repeater ID="Interventi" runat="server" DataSourceID="Interventi_Source">
<ItemTemplate>
<div>
<h2><%# (string)Eval("Titolo") %></h2>
<div style="font-weight: bold;">
<%# ((DateTime)Eval("Data")).ToString("dd/MM/yyyy hh:mm") %>,
<%# (string)Eval("NomeCategoria") %>
</div>
<div>
<%# (string)Eval("Testo") %>
</div>
</div>
</ItemTemplate>
</asp:Repeater>
<asp:SqlDataSource ID="Interventi_Source" runat="server" ProviderName="System.Data.SQLite"
ConnectionString="<%$ ConnectionStrings:ExampleBlogConnString %>"
SelectCommand="SELECT * FROM Interventi INNER JOIN Categorie ON Interventi.Categoria = Categorie.IDCategoria ORDER BY Data DESC LIMIT 10">
</asp:SqlDataSource>
</asp:View>
<asp:View ID="InterventiPerCategoria" runat="server">
<h1>
Categoria:
<asp:Literal ID="NomeCategoria" runat="server" />
</h1>
<asp:Repeater ID="InterventiCat" runat="server" DataSourceID="InterventiCat_Source">
<ItemTemplate>
<div>
<h2><%# (string)Eval("Titolo") %></h2>
<div style="font-weight: bold;">
<%# ((DateTime)Eval("Data")).ToString() %>
,
<%# (string)Eval("NomeCategoria") %>
</div>
<div>
<%# (string)Eval("Testo") %></div>
</div>
</ItemTemplate>
</asp:Repeater>
<asp:SqlDataSource ID="InterventiCat_Source" runat="server" ProviderName="System.Data.SQLite"
ConnectionString="<%$ ConnectionStrings:ExampleBlogConnString %>"
SelectCommand="SELECT * FROM Interventi INNER JOIN Categorie ON Interventi.Categoria = Categorie.IDCategoria WHERE NomeCategoria = @NomeCategoria">
<SelectParameters>
<asp:QueryStringParameter Name="@NomeCategoria" Type="string"
QueryStringField="categoria" />
</SelectParameters>
</asp:SqlDataSource>
</asp:View>
</asp:MultiView>
Si conclude così questo piccolo tutorial realizzato principalmente per mostrare le potenzialità di SQLite e del provider per ADO.Net System.Data.Sqlite.
A seconda del sistema operativo utilizzato, ASP mette a disposizione dello sviluppatore due oggetti per l’invio di email. Fino a Windows NT, infatti, l’oggetto predefinito è CDONTS, mentre da Windows 2000 in poi è obbligatorio utilizzare CDO.
Di seguito due esempi che mostrano l’uso di entrambi gli oggetti.
<%
'Creo l'oggetto
Set objCDONTS = Server.CreateObject("CDONTS.NewMail")
objCDONTS.From = "mittente@tuamail.it" 'Mittente
objCDONTS.To = "destinatario@suamail.it" 'Destinatario
objCDONTS.Subject = "Oggetto della email" 'Oggetto
objCDONTS.Body = "Testo della email" 'Testo
objCDONTS.Send 'Invio del messaggio
'Pulizia
Set objCDONTS = Nothing
%>
'Creo l'oggetto
Set objCDO = Server.CreateObject("CDO.Message")
objCDO.From = "mittente@tuamail.it" 'Mittente
objCDO.To = "destinatario@suamail.it" 'Destinatario
objCDO.Subject = "Oggetto della email" 'Oggetto
objCDO.TextBody = "Testo della email" 'Testo
objCDO.Send 'Invio del messaggio
'Pulizia
Set objCDONTS = Nothing
%>
Prendiamo, per esempio, questo codice:
<asp:DetailsView ID="DetailsView1" runat="server"
AutoGenerateRows="false" DataSourceID="SqlDataSource1">
<Fields>
<asp:BoundField DataField="ID" />
<asp:TemplateField>
<EditItemTemplate>
<asp:TextBox ID="TextBox1" runat="server"
Text='<%# (string)Eval("Nome") %>' />
</EditItemTemplate>
</asp:TemplateField>
</Fields>
</asp:DetailsView>
<asp:SqlDataSource ID="SqlDataSource1" runat="server"
SelectCommand="SELECT ID, Nome FROM TabellaDiProva WHERE ID = @ID"
UpdateCommand="UPDATE TabellaDiProva SET Nome = @Nome WHERE ID = @ID">
<SelectParameters>
<asp:QueryStringParameter Name="ID"
QueryStringField="id" />
</SelectParameters>
<UpdateParameters>
<asp:QueryStringParameter Name="ID"
QueryStringField="id" />
<asp:ControlParameter Name="Nome"
ControlID="TextBox1" />
</UpdateParameters>
</asp:SqlDataSource>
Niente di eccezionale, un controllo DetailsView con un SqlDataSource associato. Questo codice però vi restituirà il seguente errore: "Could not find control ‘TextBox1′ in ControlParameter ‘Nome’.".
Continua a leggere »