Un Blog con ASP.Net e SQLite, Seconda Parte
- Prima Parte: Creazione del Database
- Seconda Parte: Pannello di Amministrazione
- Terza Parte: Visualizzare i Post
Nell’intervento precedente ho trattato la creazione del database che utilizzeremo per memorizzare gli interventi del blog. Vedremo ora come realizzare la pagina di amministrazione, che consentirà all’autore di inserire gli interventi e le rispettive categorie.
Il login verrà gestito attraverso un Membership Provider specifico per SQLite.
Clicca qui per scaricare il progetto realizzato fino a questo punto!
Aggiunta dei file per Membership e Roles Provider
Le classi necessarie alla gestione dell’autenticazione sono MSQLiteRoleProvider.cs e MSQLiteMembershipProvider.cs e si trovano all’interno del progetto di esempio disponibile per il download in questa stessa pagina, oppure possono essere scaricate da qui.
Il files vanno posizionati nella cartella App_Code del sito. Per maggiori informazioni: Membership & Role Provider per database SQLite
Il file Web.config
Prima di iniziare la vera e propria costruzione della pagina di amministrazione, è necessario specificare alcune impostazioni nel file di configurazione. In particolare dobbiamo:
- Aggiungere una stringa di connessione al database:
<connectionStrings> <add connectionString="Data Source=|DataDirectory|blog.db;" name="ExampleBlogConnString" providerName="System.Data.SQLite"/> </connectionStrings>Notate l’uso della parola chiave
|DataDirectory|, che indica il percorso alla cartella App_Data del sito. - Forzare il login basato su Forms:
<authentication mode="Forms"/>
- Impostare i providers di autenticazione:
<membership defaultProvider="MSQLiteMembershipProvider" userIsOnlineTimeWindow="30"> <providers> <clear/> <add name="MSQLiteMembershipProvider" type="Minifloppy.it.Providers.MSQLiteMembershipProvider" connectionStringName="ExampleBlogConnString" applicationName="ExampleBlog" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="true" requiresUniqueEmail="true" passwordFormat="Hashed" writeExceptionsToEventLog="true"/> </providers> </membership> <roleManager defaultProvider="MSQLiteRoleProvider" enabled="true" cacheRolesInCookie="true" cookieName=".ASPROLES" cookieTimeout="30" cookiePath="/" cookieRequireSSL="false" cookieSlidingExpiration="true" cookieProtection="All"> <providers> <clear/> <add name="MSQLiteRoleProvider" type="Minifloppy.it.Providers.MSQLiteRoleProvider" connectionStringName="ExampleBlogConnString" applicationName="ExampleBlog" writeExceptionsToEventLog="true" /> </providers> </roleManager>
La pagina Admin.aspx
Create una nuova web form e chiamatela Admin.aspx, spuntando la casella per posizionare il codice in un file esterno e selezionando come linguaggio C#.
Ricapitolando, i compiti che la pagina dovrà svolgere sono:
- Gestione del login: svolta in automatico grazie ai providers e ai controlli lato server LoginView e Login.
- Inserimento, modifica e cancellazione degli interventi: realizzata tramite un controllo GridView e un DetailsView, associati ad un SqlDataSource.
- Inserimento, modifica e cancellazione delle categorie: realizzata tramite un controllo GridView e un DetailsView, associati ad un SqlDataSource.
Visto che vogliamo far convivere la gestione degli interventi e delle categorie in un unico file, la scelta migliore è quella di utilizzare un controllo MultiView.
Ecco quindi il codice di base:
<asp:LoginView ID="LoginView1" runat="server">
<AnonymousTemplate>
<asp:Login ID="Login1" runat="server" />
</AnonymousTemplate>
<LoggedInTemplate>
<h1>Pagina di amministrazione</h1>
<div>Benvenuto,
<asp:LoginName ID="LoginName1" runat="server" />!</div>
<div>
<asp:LinkButton ID="LinkButton1" CommandArgument="Interventi" runat="server"
OnClick="CambiaVisualizzazione_Click">Interventi</asp:LinkButton>
|
<asp:LinkButton ID="LinkButton2" CommandArgument="Categorie" runat="server"
onClick="CambiaVisualizzazione_Click">Categorie</asp:LinkButton>
|
<asp:LoginStatus ID="LoginStatus1" runat="server" /></div>
<asp:MultiView ID="AdminView" runat="server">
<asp:View ID="MostraInterventi" runat="server">
<h2>Interventi</h2>
</asp:View>
<asp:View ID="MostraCategorie" runat="server">
<h2>Categorie</h2>
</asp:View>
</asp:MultiView>
</LoggedInTemplate>
</asp:LoginView>
Notate i due LinkButton che servono a cambiare la visualizzazione. Entrambi hanno associato all’evento OnClick la stessa funzione CambiaVisualizzazione_Click, che controlla a quale vista vogliamo passare a seconda dell’attributo CommandArgument:
protected void CambiaVisualizzazione_Click(object sender,
EventArgs e)
{
LinkButton l = (LinkButton)sender;
MultiView m = (MultiView) LoginView1.FindControl("AdminView");
if (l.CommandArgument == "Interventi")
m.ActiveViewIndex = 0;
else
m.ActiveViewIndex = 1;
}
Connessione al database e creazione delle query
Per interfacciarsi al database inseriamo nella vista MostraInterventi due SqlDataSource: il primo, che sarà collegato ad un controllo GridView servirà per mostrare una lista degli interventi, il secondo, collegato ad un DetailsView, gestirà le operazioni di inserimento, modifica e cancellazione.
<asp:SqlDataSource ID="ListaInterventi_Source" runat="server"
ProviderName="System.Data.SQLite" ConnectionString="<%$ ConnectionStrings:ExampleBlogConnString %>"
SelectCommand="SELECT * FROM Interventi LEFT JOIN Categorie ON Interventi.Categoria = Categorie.IDCategoria" />
</textarea>
<textarea name="code" class="xml:nogutter" cols="60" rows="10">
<asp:SqlDataSource ID="DettagliIntervento_Source" runat="server"
ProviderName="System.Data.SQLite" ConnectionString="<%$ ConnectionStrings:ExampleBlogConnString %>"
SelectCommand="SELECT * FROM Interventi LEFT JOIN Categorie ON Interventi.Categoria = Categorie.IDCategoria WHERE IDIntervento = @IDIntervento"
DeleteCommand="DELETE FROM Interventi WHERE IDIntervento = @IDIntervento" InsertCommand="INSERT INTO Interventi (Titolo, Data, Testo, Categoria) VALUES (@Titolo, @Data, @Testo, @Categoria)"
UpdateCommand="UPDATE Interventi SET Titolo = @Titolo, Testo = @Testo, Categoria = @Categoria WHERE IDIntervento = @IDIntervento">
<SelectParameters>
<asp:ControlParameter Name="IDIntervento" ControlID="ListaInterventi" Type="Int64" />
</SelectParameters>
<DeleteParameters>
<asp:ControlParameter Name="IDIntervento" ControlID="ListaInterventi" Type="Int64" />
</DeleteParameters>
<UpdateParameters>
<asp:Parameter Name="IDIntervento" Type="Int64" />
<asp:Parameter Name="Titolo" Type="String" />
<asp:ControlParameter Name="Testo" ControlID="DettagliIntervento$Testo" Type="String"
PropertyName="Text" />
<asp:ControlParameter Name="Categoria" ControlID="DettagliIntervento$Categoria" PropertyName="SelectedValue"
Type="Int64" />
</UpdateParameters>
<InsertParameters>
<asp:Parameter Name="Titolo" Type="String" />
<asp:ControlParameter Name="Data" ControlID="DettagliIntervento$Data" Type="DateTime"
PropertyName="Text" />
<asp:ControlParameter Name="Testo" ControlID="DettagliIntervento$Testo" Type="String"
PropertyName="Text" />
<asp:ControlParameter Name="Categoria" ControlID="DettagliIntervento$Categoria" PropertyName="SelectedValue"
Type="Int64" />
</InsertParameters>
</asp:SqlDataSource>
Dobbiamo adesso fare la stessa cosa anche per le categorie, inserendo i DataSource nella vista MostraCategorie:
<asp:SqlDataSource ID="ListaCategorie_Source" runat="server"
ProviderName="System.Data.SQLite" ConnectionString="<%$ ConnectionStrings:ExampleBlogConnString %>"
SelectCommand="SELECT * FROM Categorie" />
</textarea>
<textarea name="code" class="xml:nogutter" cols="60" rows="10">
<asp:SqlDataSource ID="DettagliCategoria_Source" runat="server"
ProviderName="System.Data.SQLite" ConnectionString="<%$ ConnectionStrings:ExampleBlogConnString %>"
SelectCommand="SELECT * FROM Categorie WHERE IDCategoria = @IDCategoria"
DeleteCommand="DELETE FROM Categorie WHERE IDCategoria = @IDCategoria; UPDATE Interventi SET Categoria = -1 WHERE Categoria = @IDCategoria"
InsertCommand="INSERT INTO Categorie (NomeCategoria) VALUES (@NomeCategoria)"
UpdateCommand="UPDATE Categorie SET NomeCategoria = @NomeCategoria WHERE IDCategoria = @IDCategoria">
<SelectParameters>
<asp:ControlParameter Name="IDCategoria" ControlID="ListaCategorie" Type="Int64" />
</SelectParameters>
<DeleteParameters>
<asp:ControlParameter Name="IDCategoria" ControlID="ListaCategorie" Type="Int64" />
</DeleteParameters>
<UpdateParameters>
<asp:Parameter Name="IDCategoria" Type="Int64" />
<asp:Parameter Name="NomeCategoria" Type="String" />
</UpdateParameters>
<InsertParameters>
<asp:Parameter Name="NomeCategoria" Type="String" />
</InsertParameters>
</asp:SqlDataSource>
Come potete vedere nel secondo DataSource sono già stati predisposti tutti i parametri necessari alle query. Questi fanno riferimento ai controlli per la visualizzazione dei dati che andremo ora a creare.
Gestione degli interventi
Inseriamo nella pagina i controlli GridView e DetailsView:
<asp:GridView ID="ListaInterventi" runat="server"
AutoGenerateSelectButton="true" DataKeyNames="IDIntervento"
EmptyDataText="Nessun intervento da visualizzare."
DataSourceID="ListaInterventi_Source" AutoGenerateColumns="false"
Width="100%" OnSelectedIndexChanged="ListaInterventi_SelectedIndexChanged">
<Columns>
<asp:BoundField DataField="IDIntervento" ReadOnly="true" HeaderText="ID" />
<asp:BoundField DataField="Titolo" HeaderText="Titolo" />
<asp:BoundField DataField="Data" HeaderText="Data" />
<asp:BoundField DataField="NomeCategoria" HeaderText="Categoria" />
</Columns>
</asp:GridView>
<asp:DetailsView ID="DettagliIntervento" runat="server" DataKeyNames="IDIntervento" DefaultMode="Insert"
DataSourceID="DettagliIntervento_Source" AutoGenerateInsertButton="true"
AutoGenerateEditButton="true" AutoGenerateDeleteButton="true"
EmptyDataText="Nessun intervento selezionato." AutoGenerateRows="false"
Width="100%" OnItemDeleted="DettagliIntervento_ItemDeleted"
OnItemInserted="DettagliIntervento_ItemInserted" OnItemUpdated="DettagliIntervento_ItemUpdated">
<Fields>
<asp:BoundField DataField="IDIntervento" ReadOnly="true" Visible="false" HeaderText="ID:" />
<asp:BoundField DataField="Titolo" HeaderText="Titolo:" />
<asp:TemplateField HeaderText="Data:">
<ItemTemplate><%# (DateTime)Eval("Data") %></ItemTemplate>
<EditItemTemplate><%# (DateTime)Eval("Data")%></EditItemTemplate>
<InsertItemTemplate><asp:TextBox runat="server" ID="Data" Text='<%# DateTime.Now.ToString() %>' /></InsertItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Testo:">
<ItemTemplate><%# (string)Eval("Testo") %></ItemTemplate>
<EditItemTemplate>
<asp:TextBox runat="server" ID="Testo" TextMode="MultiLine" Columns="50" Rows="15" Text='<%# (string)Eval("Testo") %>' />
</EditItemTemplate>
<InsertItemTemplate>
<asp:TextBox runat="server" ID="Testo" TextMode="MultiLine" Columns="50" Rows="15" /></InsertItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Categoria:">
<ItemTemplate>
<%# (Eval("NomeCategoria") != DBNull.Value) ? (string)Eval("NomeCategoria") : "Nessuna categoria selezionata." %>
</ItemTemplate>
<EditItemTemplate>
<asp:DropDownList ID="Categoria" runat="server" DataTextField="NomeCategoria" DataValueField="IDCategoria"
DataSourceID="ListaCategorie_Source" AppendDataBoundItems="true"
SelectedValue='<%# (Int64)Eval("Categoria") %>'>
<asp:ListItem Value="-1">Nessuna categoria selezionata</asp:ListItem>
</asp:DropDownList>
</EditItemTemplate>
<InsertItemTemplate>
<asp:DropDownList ID="Categoria" runat="server" DataTextField="NomeCategoria" DataValueField="IDCategoria"
DataSourceID="ListaCategorie_Source" AppendDataBoundItems="true">
<asp:ListItem Selected="True" Value="-1">Nessuna categoria selezionata</asp:ListItem>
</asp:DropDownList>
</InsertItemTemplate>
</asp:TemplateField>
</Fields>
</asp:DetailsView>
#region Interventi
protected void ListaInterventi_SelectedIndexChanged(object sender, EventArgs e)
{
GridView g = (GridView)LoginView1.FindControl("AdminView$ListaInterventi");
DetailsView d = (DetailsView)LoginView1.FindControl("AdminView$DettagliIntervento");
if (g.SelectedIndex > -1)
d.ChangeMode(DetailsViewMode.ReadOnly);
}
protected void DettagliIntervento_ItemUpdated(object sender, DetailsViewUpdatedEventArgs e)
{
GridView g = (GridView)LoginView1.FindControl("AdminView$ListaInterventi");
g.DataBind();
}
protected void DettagliIntervento_ItemInserted(object sender, DetailsViewInsertedEventArgs e)
{
GridView g = (GridView)LoginView1.FindControl("AdminView$ListaInterventi");
g.DataBind();
}
protected void DettagliIntervento_ItemDeleted(object sender, DetailsViewDeletedEventArgs e)
{
GridView g = (GridView)LoginView1.FindControl("AdminView$ListaInterventi");
g.DataBind();
}
#endregion
Il codice credo che sia abbastanza auto-esplicativo e di facile comprensione, per qualsiasi dubbio lasciate un commento!
Gestione delle categorie
Il modello di funzionamento è lo stesso degli interventi:
<asp:GridView ID="ListaCategorie" runat="server"
AutoGenerateSelectButton="true" DataKeyNames="IDCategoria"
EmptyDataText="Nessuna categoria da visualizzare." DataSourceID="ListaCategorie_Source"
AutoGenerateColumns="false" Width="100%"
OnSelectedIndexChanged="ListaCategorie_SelectedIndexChanged">
<Columns>
<asp:BoundField DataField="IDCategoria" ReadOnly="true" HeaderText="ID" />
<asp:BoundField DataField="NomeCategoria" HeaderText="Nome" />
</Columns>
</asp:GridView>
</textarea>
<textarea name="code" class="xml:nogutter" cols="60" rows="10">
<asp:DetailsView ID="DettagliCategoria" runat="server"
DataKeyNames="IDCategoria" DefaultMode="Insert"
DataSourceID="DettagliCategoria_Source" AutoGenerateInsertButton="true"
AutoGenerateEditButton="true" AutoGenerateDeleteButton="true"
EmptyDataText="Nessuna categoria selezionata."
AutoGenerateRows="false" Width="100%"
OnItemDeleted="DettagliCategoria_ItemDeleted" OnItemInserted="DettagliCategoria_ItemInserted"
OnItemUpdated="DettagliCategoria_ItemUpdated">
<Fields>
<asp:BoundField DataField="IDCategoria" ReadOnly="true" Visible="false" HeaderText="ID:" InsertVisible="false" />
<asp:BoundField DataField="NomeCategoria" HeaderText="Nome:" />
</Fields>
</asp:DetailsView>
#region Categorie
protected void ListaCategorie_SelectedIndexChanged(object sender, EventArgs e)
{
GridView g = (GridView)LoginView1.FindControl("AdminView$ListaCategorie");
DetailsView d = (DetailsView)LoginView1.FindControl("AdminView$DettagliCategoria");
if (g.SelectedIndex > -1)
d.ChangeMode(DetailsViewMode.ReadOnly);
}
protected void DettagliCategoria_ItemDeleted(object sender, DetailsViewDeletedEventArgs e)
{
GridView g = (GridView)LoginView1.FindControl("AdminView$ListaCategorie");
g.DataBind();
}
protected void DettagliCategoria_ItemInserted(object sender, DetailsViewInsertedEventArgs e)
{
GridView g = (GridView)LoginView1.FindControl("AdminView$ListaCategorie");
g.DataBind();
}
protected void DettagliCategoria_ItemUpdated(object sender, DetailsViewUpdatedEventArgs e)
{
GridView g = (GridView)LoginView1.FindControl("AdminView$ListaCategorie");
g.DataBind();
}
#endregion
Si conclude qui questa seconda parte del tutorial. Nel prossimo ed ultimo intervento realizzeremo la pagina per mostrare gli interventi ai visitatori, rendendo possibile anche la navigazione per categoria e per data. A presto!
Clicca qui per scaricare il progetto realizzato fino a questo punto!