Partager via


Gestion des exceptions de niveau BLL et DAL (VB)

par Scott Mitchell

Télécharger le PDF

Dans ce tutoriel, nous allons voir comment gérer avec tactful les exceptions déclenchées pendant le flux de travail de mise à jour de DataList modifiable.

Introduction

Dans la vue d’ensemble de la modification et de la suppression de données dans le didacticiel DataList, nous avons créé une DataList qui offrait des fonctionnalités d’édition et de suppression simples. Bien qu’elle soit entièrement fonctionnelle, elle n’était guère conviviale, car toute erreur qui s’est produite pendant le processus d’édition ou de suppression a entraîné une exception non gérée. Par exemple, omettre le nom du produit ou, lors de la modification d’un produit, entrer une valeur de prix très abordable !, lève une exception. Étant donné que cette exception n’est pas interceptée dans le code, elle est en bulle jusqu’au runtime ASP.NET, ce qui affiche ensuite les détails de l’exception dans la page web.

Comme nous l’avons vu dans le didacticiel Gestion des exceptions au niveau BLL et DAL dans un didacticiel ASP.NET Page , si une exception est levée à partir des profondeurs de la logique métier ou des couches d’accès aux données, les détails de l’exception sont renvoyés à ObjectDataSource, puis à GridView. Nous avons vu comment gérer correctement ces exceptions en créant Updated ou RowUpdated en utilisant des gestionnaires d’événements pour ObjectDataSource ou GridView, en vérifiant une exception, puis en indiquant que l’exception a été gérée.

Toutefois, nos didacticiels DataList n’utilisent pas ObjectDataSource pour mettre à jour et supprimer des données. Au lieu de cela, nous travaillons directement contre la BLL. Pour détecter les exceptions provenant de BLL ou de DAL, nous devons implémenter le code de gestion des exceptions dans le code-behind de notre page ASP.NET. Dans ce tutoriel, nous allons voir comment gérer plus tactly les exceptions déclenchées lors d’un flux de travail de mise à jour de DataList modifiable.

Remarque

Dans la vue d’ensemble de la modification et de la suppression de données dans le didacticiel DataList , nous avons abordé différentes techniques pour modifier et supprimer des données de La liste de données, certaines techniques impliquées dans l’utilisation d’un ObjectDataSource pour la mise à jour et la suppression. Si vous utilisez ces techniques, vous pouvez gérer les exceptions de BLL ou DAL via les gestionnaires d’événements ou Deleted ObjectDataSourceUpdated.

Étape 1 : Création d’une liste de données modifiable

Avant de nous soucier de la gestion des exceptions qui se produisent pendant le flux de travail de mise à jour, nous allons d’abord créer une DataList modifiable. Ouvrez la ErrorHandling.aspx page dans le EditDeleteDataList dossier, ajoutez une DataList au Concepteur, définissez sa ID propriété Productssur , puis ajoutez un nouvel ObjectDataSource nommé ProductsDataSource. Configurez ObjectDataSource pour utiliser la ProductsBLL méthode s de GetProducts() classe pour sélectionner des enregistrements ; définissez les listes déroulantes dans les onglets INSERT, UPDATE et DELETE sur (None).

Retourner les informations sur le produit à l’aide de la méthode GetProducts()

Figure 1 : Retourner les informations sur le produit à l’aide de la GetProducts() méthode (Cliquez pour afficher l’image de taille complète)

Une fois l’Assistant ObjectDataSource terminé, Visual Studio crée automatiquement un ItemTemplate objet DataList. Remplacez-le par un ItemTemplate qui affiche le nom et le prix de chaque produit et inclut un bouton Modifier. Ensuite, créez un EditItemTemplate contrôle Web TextBox pour les boutons Nom et Prix et Mettre à jour et Annuler. Enfin, définissez la propriété DataList sur RepeatColumns 2.

Après ces modifications, le balisage déclaratif de votre page doit ressembler à ce qui suit. Vérifiez deux fois que les boutons Modifier, Annuler et Mettre à jour ont leurs CommandName propriétés définies respectivement sur Modifier, Annuler et Mettre à jour.

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

Remarque

Pour ce didacticiel, l’état d’affichage de DataList doit être activé.

Prenez un moment pour voir notre progression dans un navigateur (voir la figure 2).

Chaque produit inclut un bouton Modifier

Figure 2 : Chaque produit inclut un bouton Modifier (cliquez pour afficher l’image de taille complète)

Actuellement, le bouton Modifier provoque uniquement un postback qu’il ne rend pas encore modifiable le produit. Pour activer la modification, nous devons créer des gestionnaires d’événements pour dataList s EditCommand, CancelCommandet UpdateCommand des événements. Les EditCommand événements et CancelCommand les événements mettent simplement à jour la propriété de EditItemIndex DataList et rebinent les données à 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

Le UpdateCommand gestionnaire d’événements est un peu plus impliqué. Il doit lire dans les produits modifiés ProductID de la DataKeys collection ainsi que le nom et le prix du produit à partir des TextBoxes dans le EditItemTemplate, puis appeler la ProductsBLL méthode s de UpdateProduct classe avant de renvoyer DataList à son état de préversion.

Pour l’instant, utilisons simplement le même code du gestionnaire d’événements dans la vue d’ensemble de la UpdateCommand modification et de la suppression de données dans le didacticiel DataList . Nous allons ajouter le code pour gérer correctement les exceptions à l’étape 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

Face à une entrée non valide qui peut être sous la forme d’un prix unitaire mal mis en forme, une valeur de prix unitaire illégale comme -5,00 $ ou l’omission du nom du produit une exception sera levée. Dans la mesure où le UpdateCommand gestionnaire d’événements n’inclut pas de code de gestion des exceptions à ce stade, l’exception est en bulle jusqu’au runtime ASP.NET, où elle sera affichée à l’utilisateur final (voir la figure 3).

Lorsqu’une exception non gérée se produit, l’utilisateur final voit une page d’erreur

Figure 3 : Lorsqu’une exception non gérée se produit, l’utilisateur final voit une page d’erreur

Étape 2 : Gestion normale des exceptions dans le gestionnaire d’événements UpdateCommand

Pendant le flux de travail de mise à jour, les exceptions peuvent se produire dans le gestionnaire d’événements, la UpdateCommand BLL ou le DAL. Par exemple, si un utilisateur entre un prix trop cher, l’instruction Decimal.Parse du UpdateCommand gestionnaire d’événements lève une FormatException exception. Si l’utilisateur omet le nom du produit ou si le prix a une valeur négative, le DAL génère une exception.

Lorsqu’une exception se produit, nous voulons afficher un message informatif dans la page elle-même. Ajoutez un contrôle Web Label à la page dont ID la valeur est définie ExceptionDetails. Configurez le texte de l’étiquette pour qu’il s’affiche en rouge, en gras, en gras et en italique en affectant sa CssClass propriété à la Warning classe CSS, qui est définie dans le Styles.css fichier.

Lorsqu’une erreur se produit, nous voulons que l’étiquette soit affichée une seule fois. Autrement dit, lors des publications ultérieures, le message d’avertissement de l’étiquette doit disparaître. Pour ce faire, effacez la propriété d’étiquette Text ou les paramètres de False sa Visible propriété dans le Page_Load gestionnaire d’événements (comme nous l’avons fait dans la gestion des exceptions au niveau BLL et DAL dans un didacticiel ASP.NET Page) ou en désactivant la prise en charge de l’état d’affichage de l’étiquette. Utilisons cette dernière option.

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

Lorsqu’une exception est levée, nous allons affecter les détails de l’exception à la ExceptionDetails propriété du Text contrôle Label. Étant donné que son état d’affichage est désactivé, les modifications programmatiques de la Text propriété seront perdues, en revenant au texte par défaut (une chaîne vide), masquant ainsi le message d’avertissement.

Pour déterminer quand une erreur a été générée afin d’afficher un message utile sur la page, nous devons ajouter un Try ... Catch bloc au UpdateCommand gestionnaire d’événements. La Try partie contient du code qui peut entraîner une exception, tandis que le Catch bloc contient du code exécuté face à une exception. Consultez la section Principes de base de la gestion des exceptions dans la documentation .NET Framework pour plus d’informations sur le Try ... Catch bloc.

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

Lorsqu’une exception de tout type est levée par du code dans le Try bloc, le Catch code du bloc commence à s’exécuter. Le type d’exception levée DbException, NoNullAllowedException, ArgumentExceptionet ainsi de suite dépend de ce qui, exactement, a précédé l’erreur au premier endroit. S’il existe un problème au niveau de la base de données, une DbException opération est levée. Si une valeur non valide est entrée pour les UnitPricechamps , ou UnitsOnOrderUnitsInStockReorderLevel les champs, une ArgumentException valeur est levée, car nous avons ajouté du code pour valider ces valeurs de champ dans la classe (consultez le ProductsDataTable didacticiel Création d’une couche logique métier).

Nous pouvons fournir une explication plus utile à l’utilisateur final en basant le texte du message sur le type d’exception intercepté. Le code suivant qui a été utilisé dans un formulaire presque identique dans la gestion des exceptions au niveau BLL et DAL dans un didacticiel ASP.NET Page fournit ce niveau de détail :

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

Pour suivre ce tutoriel, appelez simplement la DisplayExceptionDetails méthode du Catch bloc passant l’instance interceptée Exception (ex).

Avec le Try ... Catch bloc en place, les utilisateurs sont présentés avec un message d’erreur plus informatif, comme le montrent les figures 4 et 5. Notez que, face à une exception, dataList reste en mode édition. Cela est dû au fait qu’une fois l’exception effectuée, le flux de contrôle est immédiatement redirigé vers le Catch bloc, en contournant le code qui retourne La liste de données à son état de préversion.

Un message d’erreur s’affiche si un utilisateur omet un champ obligatoire

Figure 4 : Un message d’erreur s’affiche si un utilisateur omet un champ obligatoire (cliquez pour afficher l’image de taille complète)

Un message d’erreur s’affiche lors de l’entrée d’un prix négatif

Figure 5 : Un message d’erreur s’affiche lors de l’entrée d’un prix négatif (cliquez pour afficher l’image de taille complète)

Résumé

GridView et ObjectDataSource fournissent des gestionnaires d’événements de niveau post-niveau qui incluent des informations sur les exceptions qui ont été déclenchées pendant la mise à jour et la suppression du flux de travail, ainsi que les propriétés qui peuvent être définies pour indiquer si l’exception a été gérée ou non. Toutefois, ces fonctionnalités ne sont pas disponibles lors de l’utilisation de DataList et de l’utilisation directe de la base de données. Au lieu de cela, nous sommes responsables de l’implémentation de la gestion des exceptions.

Dans ce tutoriel, nous avons vu comment ajouter la gestion des exceptions à un flux de travail de mise à jour de DataList modifiable en ajoutant un Try ... Catch bloc au UpdateCommand gestionnaire d’événements. Si une exception est levée pendant le flux de travail de mise à jour, le Catch code du bloc s’exécute, affichant des informations utiles dans l’étiquette ExceptionDetails .

À ce stade, DataList ne fait aucun effort pour empêcher les exceptions de se produire en premier lieu. Même si nous savons qu’un prix négatif entraînera une exception, nous n’avons pas encore ajouté de fonctionnalité pour empêcher de manière proactive un utilisateur d’entrer une telle entrée non valide. Dans notre prochain tutoriel, nous allons voir comment réduire les exceptions provoquées par une entrée utilisateur non valide en ajoutant des contrôles de validation dans le EditItemTemplate.

Bonne programmation !

Pour aller plus loin

Pour plus d’informations sur les sujets abordés dans ce tutoriel, consultez les ressources suivantes :

À propos de l’auteur

Scott Mitchell, auteur de sept livres ASP/ASP.NET et fondateur de 4GuysFromRolla.com, travaille avec les technologies Web Microsoft depuis 1998. Scott travaille en tant que consultant indépendant, formateur et écrivain. Son dernier livre est Sams Teach Yourself ASP.NET 2.0 en 24 heures. Il peut être accessible à mitchell@4GuysFromRolla.com. ou via son blog, qui peut être trouvé à http://ScottOnWriting.NET.

Merci spécial à

Cette série de tutoriels a été examinée par de nombreux réviseurs utiles. Le réviseur principal de ce didacticiel était Ken Pespisa. Vous souhaitez consulter mes prochains articles MSDN ? Si c’est le cas, déposez-moi une ligne à mitchell@4GuysFromRolla.com.