Condividi tramite


Gestione delle eccezioni a livello BLL e DAL (VB)

di Scott Mitchell

Scarica PDF

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 nell'esercitazione DataList è stato creato un oggetto DataList che offre funzionalità di modifica ed eliminazione semplici. 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 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 l'LL. 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.

Nota

Nell'esercitazione Panoramica della modifica e dell'eliminazione di dati nell'esercitazione DataList sono state illustrate diverse tecniche per la modifica e l'eliminazione di dati da DataList, alcune tecniche coinvolte nell'uso di objectDataSource per l'aggiornamento e l'eliminazione. Se si usano queste tecniche, è possibile gestire le eccezioni da BLL o DAL tramite i gestori eventi o Updated ObjectDataSourceDeleted.

Passaggio 1: Creazione di un oggetto DataList modificabile

Prima di preoccuparsi della gestione delle eccezioni che si verificano durante il flusso di lavoro di aggiornamento, è possibile creare prima un Oggetto DataList modificabile. Aprire la ErrorHandling.aspx pagina nella EditDeleteDataList cartella , aggiungere un oggetto DataList alla finestra di progettazione, impostarne la ID proprietà su Productse aggiungere un nuovo ObjectDataSource denominato ProductsDataSource. Configurare ObjectDataSource per l'utilizzo del ProductsBLL metodo della GetProducts() classe per la selezione dei record. Impostare gli elenchi a discesa nelle schede INSERT, UPDATE e DELETE su (Nessuno).

Restituire le informazioni sul prodotto utilizzando il metodo GetProducts()

Figura 1: Restituire le informazioni sul prodotto usando il metodo (fare clic per visualizzare l'immagine 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>

Nota

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).

Ogni prodotto include un pulsante Modifica

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 , e EditCommand di CancelCommandUpdateCommandDataList. Gli EditCommand eventi e CancelCommand aggiornano semplicemente la proprietà DataList s EditItemIndex e riassociato i dati a DataList:

Protected Sub Products_EditCommand(source As Object, e As DataListCommandEventArgs) _
    Handles Products.EditCommand
    ' 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()
End Sub
Protected Sub Products_CancelCommand(source As Object, e As DataListCommandEventArgs) _
    Handles Products.CancelCommand
    ' Set the DataList's EditItemIndex property to -1
    Products.EditItemIndex = -1
    ' Rebind the data to the DataList
    Products.DataBind()
End Sub

Il UpdateCommand gestore eventi è un po' più coinvolto. È necessario leggere nel prodotto modificato s ProductID dalla DataKeys raccolta insieme al nome e al prezzo del prodotto da TextBoxes in EditItemTemplatee quindi chiamare il ProductsBLL metodo della UpdateProduct classe prima di restituire DataList allo stato di pre-modifica.

Per il momento, è sufficiente usare lo stesso codice UpdateCommand del gestore eventi nell'esercitazione Panoramica della modifica e dell'eliminazione di dati nell'esercitazione DataList . Il codice verrà aggiunto per gestire correttamente le eccezioni nel passaggio 2.

Protected Sub Products_UpdateCommand(source As Object, e As DataListCommandEventArgs) _
    Handles Products.UpdateCommand
    ' Read in the ProductID from the DataKeys collection
    Dim productID As Integer = Convert.ToInt32(Products.DataKeys(e.Item.ItemIndex))
    ' Read in the product name and price values
    Dim productName As TextBox = CType(e.Item.FindControl("ProductName"), TextBox)
    Dim unitPrice As TextBox = CType(e.Item.FindControl("UnitPrice"), TextBox)
    Dim productNameValue As String = Nothing
    If productName.Text.Trim().Length > 0 Then
        productNameValue = productName.Text.Trim()
    End If
    Dim unitPriceValue As Nullable(Of Decimal) = Nothing
    If unitPrice.Text.Trim().Length > 0 Then
        unitPriceValue = Decimal.Parse(unitPrice.Text.Trim(), _
                         System.Globalization.NumberStyles.Currency)
    End If
    ' Call the ProductsBLL's UpdateProduct method...
    Dim productsAPI As New ProductsBLL()
    productsAPI.UpdateProduct(productNameValue, unitPriceValue, productID)
    ' Revert the DataList back to its pre-editing state
    Products.EditItemIndex = -1
    Products.DataBind()
End Sub

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).

Quando si verifica un'eccezione non gestita, l'utente finale visualizza una pagina di errore

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, il 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 la cui ID proprietà è 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. Ovvero, nei postback successivi, il messaggio di avviso etichetta dovrebbe scomparire. A tale scopo, è possibile cancellare la proprietà Label s Text o impostarne Visible la proprietà su False nel Page_Load gestore eventi (come è stato fatto di nuovo nell'esercitazione Gestione delle eccezioni BLL- e DAL-Level in una ASP.NET Page ) o disabilitando il supporto dello stato di visualizzazione dell'etichetta. Usare quest'ultima opzione.

<asp:Label ID="ExceptionDetails" EnableViewState="False" CssClass="Warning"
    runat="server" />

Quando viene generata un'eccezione, verranno assegnati i dettagli dell'eccezione alla ExceptionDetails proprietà del Text controllo Label. 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 Try ... Catch nella documentazione di .NET Framework.

Protected Sub Products_UpdateCommand(source As Object, e As DataListCommandEventArgs) _
    Handles Products.UpdateCommand
    ' Handle any exceptions raised during the editing process
    Try
        ' Read in the ProductID from the DataKeys collection
        Dim productID As Integer = _
            Convert.ToInt32(Products.DataKeys(e.Item.ItemIndex))
        ... Some code omitted for brevity ...
    Catch ex As Exception
        ' TODO: Display information about the exception in ExceptionDetails
    End Try
End Sub

Quando viene generata un'eccezione di qualsiasi tipo dal codice all'interno del Try blocco, il Catch codice del blocco inizierà l'esecuzione. Il tipo di eccezione generata DbException, NoNullAllowedException, ArgumentExceptione 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 UnitPricecampi , UnitsInStock, UnitsOnOrdero ReorderLevel , verrà generata un'eccezione ArgumentException , come è stato aggiunto il codice per convalidare questi valori di campo nella ProductsDataTable classe (vedere l'esercitazione Creazione di un livello di logica di business).

È possibile fornire una spiegazione più utile all'utente finale basando il testo del messaggio sul tipo di eccezione rilevata. Il codice seguente usato in un modulo quasi identico nell'esercitazione Gestione delle eccezioni BLL e DAL in un'esercitazione ASP.NET Page fornisce questo livello di dettaglio:

Private Sub DisplayExceptionDetails(ByVal ex As Exception)
    ' Display a user-friendly message
    ExceptionDetails.Text = "There was a problem updating the product. "
    If TypeOf ex Is System.Data.Common.DbException Then
        ExceptionDetails.Text += "Our database is currently experiencing problems." + _
                                 "Please try again later."
    ElseIf TypeOf ex Is System.Data.NoNullAllowedException Then
        ExceptionDetails.Text+="There are one or more required fields that are missing."
    ElseIf TypeOf ex Is ArgumentException Then
        Dim paramName As String = CType(ex, ArgumentException).ParamName
        ExceptionDetails.Text+=String.Concat("The ", paramName, " value is illegal.")
    ElseIf TypeOf ex Is ApplicationException Then
        ExceptionDetails.Text += ex.Message
    End If
End Sub

Per completare questa esercitazione, è sufficiente chiamare il DisplayExceptionDetails metodo dal Catch blocco passando l'istanza intercettata 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.

Viene visualizzato un messaggio di errore se un utente omette un campo obbligatorio

Figura 4: Viene visualizzato un messaggio di errore se un utente omette un campo obbligatorio (fare clic per visualizzare l'immagine a dimensione intera)

Viene visualizzato un messaggio di errore quando si immette un prezzo negativo

Figura 5: Viene visualizzato un messaggio di errore quando si immette un prezzo negativo (fare clic per visualizzare l'immagine a dimensione intera)

Riepilogo

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. È invece responsabile 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, viene eseguito il Catch codice del blocco, visualizzando informazioni utili nell'etichetta ExceptionDetails .

A questo punto, DataList non fa alcun sforzo per impedire che le eccezioni si verifichino al primo posto. 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:

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 utili. Il revisore principale per questa esercitazione era Ken Pespisa. Si è interessati a esaminare i prossimi articoli MSDN? In tal caso, mandami un messaggio a mitchell@4GuysFromRolla.com.