Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
In questa esercitazione verrà illustrato come gestire correttamente le eccezioni generate durante un flusso di lavoro di aggiornamento di DataList modificabile.
Introduzione
Nell'esercitazione Panoramica della modifica e dell'eliminazione di dati nel DataList è stato creato un DataList che offre semplici funzionalità di modifica ed eliminazione. Sebbene completamente funzionante, non era facile da usare, poiché qualsiasi errore che si è verificato durante il processo di modifica o eliminazione ha generato un'eccezione non gestita. Ad esempio, omettendo il nome del prodotto o, quando si modifica un prodotto, immettendo un valore di prezzo molto conveniente!, viene generata un'eccezione. Poiché questa eccezione non viene intercettata nel codice, viene visualizzata fino al runtime di ASP.NET, che quindi visualizza i dettagli dell'eccezione nella pagina Web.
Come illustrato nell'esercitazione Sulla gestione delle eccezioni BLL e DAL-Level in una pagina ASP.NET , se viene generata un'eccezione dalle profondità della logica di business o dei livelli di accesso ai dati, i dettagli dell'eccezione vengono restituiti a ObjectDataSource e quindi a GridView. È stato illustrato come gestire correttamente queste eccezioni creando Updated
gestori eventi o RowUpdated
per ObjectDataSource o GridView, verificando un'eccezione e quindi indicando che l'eccezione è stata gestita.
Le esercitazioni di DataList, tuttavia, non usano ObjectDataSource per l'aggiornamento e l'eliminazione di dati. Al contrario, stiamo lavorando direttamente contro il BLL. Per rilevare le eccezioni provenienti da BLL o DAL, è necessario implementare il codice di gestione delle eccezioni all'interno del code-behind della pagina ASP.NET. In questa esercitazione verrà illustrato come gestire in modo più immediato le eccezioni generate durante un flusso di lavoro di aggiornamento di DataList modificabile.
Annotazioni
Nella panoramica sulla modifica e l'eliminazione dei dati nel DataList sono state illustrate diverse tecniche per la modifica e l'eliminazione di dati dal DataList, alcune delle quali prevedono l'uso di ObjectDataSource per l'aggiornamento e l'eliminazione. Se si impiegano queste tecniche, è possibile gestire le eccezioni dal BLL o DAL tramite i gestori eventi dell'ObjectDataSource Updated
o Deleted
.
Passaggio 1: Creazione di un oggetto DataList modificabile
Prima di preoccuparci della gestione delle eccezioni che si verificano durante il flusso di lavoro di aggiornamento, creiamo prima un DataList modificabile. Aprire la ErrorHandling.aspx
pagina nella EditDeleteDataList
cartella , aggiungere un oggetto DataList alla finestra di progettazione, impostarne la ID
proprietà su Products
e aggiungere un nuovo ObjectDataSource denominato ProductsDataSource
. Configurare ObjectDataSource per utilizzare il metodo della classe ProductsBLL
GetProducts()
per la selezione dei record. Impostare gli elenchi a discesa nelle schede INSERT, UPDATE e DELETE su (Nessuno).
Figura 1: Restituire le informazioni sul prodotto usando il metodo (GetProducts()
a dimensione intera)
Dopo aver completato la procedura guidata ObjectDataSource, Visual Studio creerà automaticamente un oggetto ItemTemplate
per DataList. Sostituirlo con un oggetto ItemTemplate
che visualizza il nome e il prezzo di ogni prodotto e include un pulsante Modifica. Creare quindi un oggetto EditItemTemplate
con un controllo Web TextBox per i pulsanti nome e prezzo e Aggiorna e Annulla. Impostare infine la proprietà DataList s RepeatColumns
su 2.
Dopo queste modifiche, il markup dichiarativo della pagina dovrebbe essere simile al seguente. Verificare che i pulsanti Modifica, Annulla e Aggiorna abbiano le relative CommandName
proprietà impostate rispettivamente su Modifica, Annulla e Aggiorna.
<asp:DataList ID="Products" runat="server" DataKeyField="ProductID"
DataSourceID="ProductsDataSource" RepeatColumns="2">
<ItemTemplate>
<h5>
<asp:Label runat="server" ID="ProductNameLabel"
Text='<%# Eval("ProductName") %>' />
</h5>
Price:
<asp:Label runat="server" ID="Label1"
Text='<%# Eval("UnitPrice", "{0:C}") %>' />
<br />
<asp:Button runat="server" id="EditProduct" CommandName="Edit"
Text="Edit" />
<br />
<br />
</ItemTemplate>
<EditItemTemplate>
Product name:
<asp:TextBox ID="ProductName" runat="server"
Text='<%# Eval("ProductName") %>' />
<br />
Price:
<asp:TextBox ID="UnitPrice" runat="server"
Text='<%# Eval("UnitPrice", "{0:C}") %>' />
<br />
<br />
<asp:Button ID="UpdateProduct" runat="server" CommandName="Update"
Text="Update" />
<asp:Button ID="CancelUpdate" runat="server" CommandName="Cancel"
Text="Cancel" />
</EditItemTemplate>
</asp:DataList>
<asp:ObjectDataSource ID="ProductsDataSource" runat="server"
SelectMethod="GetProducts" TypeName="ProductsBLL"
OldValuesParameterFormatString="original_{0}">
</asp:ObjectDataSource>
Annotazioni
Per questa esercitazione è necessario abilitare lo stato di visualizzazione di DataList.
Dedicare qualche istante alla visualizzazione dello stato di avanzamento tramite un browser (vedere la figura 2).
Figura 2: Ogni prodotto include un pulsante di modifica (fare clic per visualizzare l'immagine a dimensione intera)
Attualmente, il pulsante Modifica causa solo un postback che non rende ancora modificabile il prodotto. Per abilitare la modifica, è necessario creare gestori eventi per gli eventi EditCommand
, CancelCommand
e UpdateCommand
del DataList. Gli eventi EditCommand
e CancelCommand
aggiornano semplicemente la proprietà EditItemIndex
del DataList e riassocia i dati al DataList.
protected void Products_EditCommand(object source, DataListCommandEventArgs e)
{
// Set the DataList's EditItemIndex property to the
// index of the DataListItem that was clicked
Products.EditItemIndex = e.Item.ItemIndex;
// Rebind the data to the DataList
Products.DataBind();
}
protected void Products_CancelCommand(object source, DataListCommandEventArgs e)
{
// Set the DataList's EditItemIndex property to -1
Products.EditItemIndex = -1;
// Rebind the data to the DataList
Products.DataBind();
}
Il UpdateCommand
gestore eventi è un po' più coinvolto. È necessario leggere il prodotto modificato ProductID
dalla raccolta DataKeys
insieme al nome del prodotto e al prezzo dalle TextBox in EditItemTemplate
, e quindi chiamare il metodo ProductsBLL
della classe UpdateProduct
prima di riportare la DataList allo stato pre-modifica.
Per il momento, usiamo esattamente lo stesso codice UpdateCommand
del gestore eventi nella guida Panoramica della modifica e dell'eliminazione di dati nel DataList. Il codice verrà aggiunto per gestire correttamente le eccezioni nel passaggio 2.
protected void Products_UpdateCommand(object source, DataListCommandEventArgs e)
{
// Read in the ProductID from the DataKeys collection
int productID = Convert.ToInt32(Products.DataKeys[e.Item.ItemIndex]);
// Read in the product name and price values
TextBox productName = (TextBox)e.Item.FindControl("ProductName");
TextBox unitPrice = (TextBox)e.Item.FindControl("UnitPrice");
string productNameValue = null;
if (productName.Text.Trim().Length > 0)
productNameValue = productName.Text.Trim();
decimal? unitPriceValue = null;
if (unitPrice.Text.Trim().Length > 0)
unitPriceValue = Decimal.Parse(unitPrice.Text.Trim(),
System.Globalization.NumberStyles.Currency);
// Call the ProductsBLL's UpdateProduct method...
ProductsBLL productsAPI = new ProductsBLL();
productsAPI.UpdateProduct(productNameValue, unitPriceValue, productID);
// Revert the DataList back to its pre-editing state
Products.EditItemIndex = -1;
Products.DataBind();
}
In caso di input non valido che può essere sotto forma di un prezzo unitario formattato in modo non corretto, un valore di prezzo unitario illegale come -$5,00 o l'omissione del nome del prodotto verrà generata un'eccezione. Poiché il UpdateCommand
gestore eventi non include alcun codice di gestione delle eccezioni a questo punto, l'eccezione passerà al runtime di ASP.NET, in cui verrà visualizzata all'utente finale (vedere la figura 3).
Figura 3: Quando si verifica un'eccezione non gestita, l'utente finale visualizza una pagina di errore
Passaggio 2: Gestire correttamente le eccezioni nel gestore eventi UpdateCommand
Durante il flusso di lavoro di aggiornamento, le eccezioni possono verificarsi nel gestore eventi, nel UpdateCommand
BLL o nel DAL. Ad esempio, se un utente immette un prezzo troppo costoso, l'istruzione Decimal.Parse
nel UpdateCommand
gestore eventi genererà un'eccezione FormatException
. Se l'utente omette il nome del prodotto o se il prezzo ha un valore negativo, la DAL genererà un'eccezione.
Quando si verifica un'eccezione, si vuole visualizzare un messaggio informativo all'interno della pagina stessa. Aggiungere un controllo Web Etichetta alla pagina in cui la proprietà ID
è impostata su ExceptionDetails
. Configurare il testo dell'etichetta in modo che venga visualizzato in un tipo di carattere rosso, extra-large, grassetto e corsivo assegnando la relativa CssClass
proprietà alla Warning
classe CSS, definita nel Styles.css
file.
Quando si verifica un errore, si vuole che l'etichetta venga visualizzata una sola volta. Cioè, nei postback successivi, il messaggio di avviso della label dovrebbe scomparire. A tale scopo, è possibile cancellare la proprietà del Label Text
o impostare la sua proprietà Visible
su False
nel gestore eventi Page_Load
(come fatto in precedenza nell'esercitazione Gestione delle eccezioni BLL e DAL-Level in una pagina ASP.NET) o disabilitando il supporto dello stato di visualizzazione del Label. Usare quest'ultima opzione.
<asp:Label ID="ExceptionDetails" EnableViewState="False" CssClass="Warning"
runat="server" />
Quando si verifica un'eccezione, assegneremo i dettagli dell'eccezione alla proprietà del controllo Label ExceptionDetails
. Poiché il relativo stato di visualizzazione è disabilitato, nei postback successivi le modifiche a livello di codice della Text
proprietà andranno perse, ripristinando il testo predefinito (una stringa vuota), nascondendo così il messaggio di avviso.
Per determinare quando è stato generato un errore per visualizzare un messaggio utile nella pagina, è necessario aggiungere un Try ... Catch
blocco al UpdateCommand
gestore eventi. La Try
parte contiene codice che può causare un'eccezione, mentre il Catch
blocco contiene codice eseguito in caso di eccezione. Per altre informazioni sul blocco, vedere la sezione Try ... Catch
nella documentazione di .NET Framework.
protected void Products_UpdateCommand(object source, DataListCommandEventArgs e)
{
// Handle any exceptions raised during the editing process
try
{
// Read in the ProductID from the DataKeys collection
int productID = Convert.ToInt32(Products.DataKeys[e.Item.ItemIndex]);
... Some code omitted for brevity ...
}
catch (Exception ex)
{
// TODO: Display information about the exception in ExceptionDetails
}
}
Quando viene generata dal codice all'interno del blocco Try
un'eccezione di qualsiasi tipo, il codice del blocco Catch
inizierà a essere eseguito. Il tipo di eccezione generata DbException
, NoNullAllowedException
, ArgumentException
e così via dipende da ciò che, esattamente, ha precipitato l'errore al primo posto. Se si verifica un problema a livello di database, verrà generata un'eccezione DbException
. Se viene immesso un valore non valido per i campi UnitPrice
, UnitsInStock
, UnitsOnOrder
o ReorderLevel
, verrà generata un'eccezione ArgumentException
poiché abbiamo aggiunto il codice per convalidare questi valori di campo nella classe ProductsDataTable
(vedere l'esercitazione Creazione di un Livello Logico Aziendale).
È possibile fornire una spiegazione più utile all'utente finale basando il testo del messaggio sul tipo di eccezione rilevata. Il codice seguente, utilizzato in una forma quasi identica nell'esercitazione precedente Gestione delle eccezioni BLL e DAL-Level in una pagina ASP.NET, fornisce questo livello di dettaglio:
private void DisplayExceptionDetails(Exception ex)
{
// Display a user-friendly message
ExceptionDetails.Text = "There was a problem updating the product. ";
if (ex is System.Data.Common.DbException)
ExceptionDetails.Text += "Our database is currently experiencing problems.
Please try again later.";
else if (ex is NoNullAllowedException)
ExceptionDetails.Text += "There are one or more required fields that are
missing.";
else if (ex is ArgumentException)
{
string paramName = ((ArgumentException)ex).ParamName;
ExceptionDetails.Text +=
string.Concat("The ", paramName, " value is illegal.");
}
else if (ex is ApplicationException)
ExceptionDetails.Text += ex.Message;
}
Per completare questa esercitazione, è sufficiente chiamare il metodo DisplayExceptionDetails
dal blocco Catch
passando l'istanza catturata Exception
(ex
).
Con il Try ... Catch
blocco sul posto, agli utenti viene visualizzato un messaggio di errore più informativo, come illustrato nella figura 4 e 5. Si noti che, in caso di eccezione, DataList rimane in modalità di modifica. Ciò è dovuto al fatto che una volta che si verifica l'eccezione, il flusso di controllo viene immediatamente reindirizzato al Catch
blocco, ignorando il codice che restituisce DataList allo stato di pre-modifica.
Figura 4: Viene visualizzato un messaggio di errore se un utente omette un campo obbligatorio (fare clic per visualizzare l'immagine a dimensione intera)
Figura 5: Viene visualizzato un messaggio di errore quando si immette un prezzo negativo (fare clic per visualizzare l'immagine a dimensione intera)
Riassunto
GridView e ObjectDataSource forniscono gestori eventi post-livello che includono informazioni su eventuali eccezioni generate durante l'aggiornamento e l'eliminazione del flusso di lavoro, nonché proprietà che possono essere impostate per indicare se l'eccezione è stata gestita o meno. Queste funzionalità, tuttavia, non sono disponibili quando si lavora con DataList e si usa direttamente il BLL. Siamo invece responsabili dell'implementazione della gestione delle eccezioni.
In questa esercitazione è stato illustrato come aggiungere la gestione delle eccezioni a un flusso di lavoro di aggiornamento di DataList modificabile aggiungendo un Try ... Catch
blocco al UpdateCommand
gestore eventi. Se viene generata un'eccezione durante il flusso di lavoro di aggiornamento, il codice del blocco Catch
viene eseguito, visualizzando informazioni utili nella Label ExceptionDetails
.
A questo punto, DataList non si sforza minimamente di impedire che le eccezioni si verifichino. Anche se sappiamo che un prezzo negativo genererà un'eccezione, non abbiamo ancora aggiunto alcuna funzionalità per impedire a un utente di immettere tale input non valido in modo proattivo. Nell'esercitazione successiva verrà illustrato come ridurre le eccezioni causate dall'input dell'utente non valido aggiungendo controlli di convalida in EditItemTemplate
.
Buon programmatori!
Altre informazioni
Per altre informazioni sugli argomenti illustrati in questa esercitazione, vedere le risorse seguenti:
- Linee guida di progettazione per le eccezioni
- Moduli di registrazione degli errori e gestori (ELMAH) ( una libreria open source per la registrazione degli errori)
- Libreria enterprise per .NET Framework 2.0 (include il blocco di applicazioni di gestione delle eccezioni)
Informazioni sull'autore
Scott Mitchell, autore di sette libri ASP/ASP.NET e fondatore di 4GuysFromRolla.com, ha lavorato con le tecnologie Web Microsoft dal 1998. Scott lavora come consulente indipendente, formatore e scrittore. Il suo ultimo libro è Sams Teach Yourself ASP.NET 2.0 in 24 ore. Può essere raggiunto a mitchell@4GuysFromRolla.com.
Grazie speciale a
Questa serie di esercitazioni è stata esaminata da molti revisori competenti. Il revisore principale per questo tutorial era Ken Pespisa. Si è interessati a esaminare i prossimi articoli MSDN? In tal caso, mandami un messaggio a mitchell@4GuysFromRolla.com.