Partager via


Gestion des exceptions de niveau BLL et DAL (C#)

par Scott Mitchell

Télécharger le PDF

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

Introduction

Dans le didacticiel Vue d’ensemble de la modification et de la suppression de données du datalist , nous avons créé une DataList qui offrait des fonctionnalités d’édition et de suppression simples. Bien que entièrement fonctionnel, il n’était guère convivial, car toute erreur qui s’est produite pendant le processus de modification 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 de Très abordable !, lève une exception. Étant donné que cette exception n’est pas interceptée dans le code, elle s’affiche dans le ASP.NET runtime, qui affiche ensuite les détails de l’exception dans la page web.

Comme nous l’avons vu dans le didacticiel Gestion des exceptions BLL- et DAL-Level dans un ASP.NET Page , si une exception est levée à partir des profondeurs des couches de logique métier ou 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 des gestionnaires d’événements ou RowUpdated pour ObjectDataSource ou GridView, en vérifiant la recherche d’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 le BLL. Pour détecter les exceptions provenant du BLL ou du 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 avec tact les exceptions déclenchées lors d’un flux de travail de mise à jour de DataList modifiable.

Notes

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

É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, commençons par créer une datalist modifiable. Ouvrez la ErrorHandling.aspx page dans le EditDeleteDataList dossier, ajoutez un DataList au Designer, définissez sa ID propriété sur Products, puis ajoutez un nouvel ObjetDataSource nommé ProductsDataSource. Configurez ObjectDataSource pour utiliser la méthode de classe ProductsBLL s GetProducts() pour sélectionner des enregistrements ; définissez les listes déroulantes des onglets INSERT, UPDATE et DELETE sur (Aucun).

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 (cliquer pour afficher l’image en taille réelle)

Une fois l’Assistant ObjectDataSource terminé, Visual Studio crée automatiquement un ItemTemplate pour datalist. Remplacez cette valeur par un ItemTemplate qui affiche le nom et le prix de chaque produit et inclut un bouton Modifier. Ensuite, créez un EditItemTemplate avec un contrôle Web TextBox pour le nom et le prix et les boutons 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. Double-case activée pour s’assurer que les propriétés des boutons Modifier, Annuler et Mettre à jour sont CommandName respectivement définies 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>

Notes

Pour ce tutoriel, 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 comprend un bouton Modifier

Figure 2 : Chaque produit comprend un bouton Modifier (cliquer pour afficher l’image en taille réelle)

Actuellement, le bouton Modifier provoque uniquement une publication qui ne rend pas encore le produit modifiable. Pour activer la modification, nous devons créer des gestionnaires d’événements pour les événements DataList, EditCommandCancelCommand, et UpdateCommand . Les EditCommand événements et CancelCommand mettent simplement à jour la propriété de EditItemIndex DataList et relient les données à la 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();
}

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

Pour l’instant, nous allons simplement utiliser exactement le même code que celui UpdateCommand du gestionnaire d’événements dans le didacticiel Vue d’ensemble de la modification et de la suppression des données du datalist . Nous allons ajouter le code pour gérer correctement les exceptions à l’étape 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();
}

En cas d’entrée non valide qui peut être sous la forme d’un prix unitaire mal mis en forme, d’une valeur de prix unitaire illégale comme -5,00 $ ou de l’omission du nom du produit, une exception sera levée. Étant donné que le UpdateCommand gestionnaire d’événements n’inclut aucun code de gestion des exceptions à ce stade, l’exception s’affiche 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 appropriée des exceptions dans le gestionnaire d’événements UpdateCommand

Pendant le flux de travail de mise à jour, des exceptions peuvent se produire dans le UpdateCommand gestionnaire d’événements, le BLL ou le DAL. Par exemple, si un utilisateur entre un prix trop cher, l’instruction Decimal.Parse dans le 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 lève une exception.

Lorsqu’une exception se produit, nous voulons afficher un message d’information dans la page elle-même. Ajoutez un contrôle Label Web à la page dont ID est défini sur ExceptionDetails. Configurez le texte de l’étiquette pour qu’il s’affiche dans une police rouge, extra-volumineuse, en gras et 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 ne s’affiche qu’une seule fois. Autrement dit, lors des publications ultérieures, le message d’avertissement de l’étiquette doit disparaître. Pour ce faire, vous pouvez supprimer la propriété label ou Text les paramètres de sa Visible propriété False dans le Page_Load gestionnaire d’événements (comme nous l’avons fait dans le didacticiel Gestion des exceptions BLL- et DAL-Level dans un 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é, lors des publications ultérieures, les modifications de programmation de la Text propriété seront perdues, rétablissant le 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 gestionnaire d’événements UpdateCommand . La Try partie contient du code qui peut entraîner une exception, tandis que le bloc contient du Catch code exécuté en face d’une exception. Pour plus d’informations sur le bloc, consultez la section Principes fondamentaux de la gestion des exceptions dans la Try ... Catch documentation .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
    }
}

Lorsqu’une exception d’un type quelconque 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, ArgumentException, et ainsi de suite dépend de ce qui, exactement, a précipité l’erreur en premier lieu. En cas de problème au niveau de la base de données, un DbException est levée. Si une valeur non conforme est entrée pour les UnitPricechamps , UnitsInStock, UnitsOnOrderou ReorderLevel , une est levée, car nous avons ajouté du ArgumentException code pour valider ces valeurs de champ dans la ProductsDataTable classe (voir le didacticiel Création d’une couche de 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ée. Le code suivant qui a été utilisé sous une forme presque identique dans le didacticiel Gestion des exceptions BLL- et DAL-Level dans une page ASP.NET fournit ce niveau de détail :

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

Pour suivre ce didacticiel, appelez simplement la DisplayExceptionDetails méthode à partir du Catch bloc en passant dans le instance intercepté Exception (ex).

Une fois le Try ... Catch bloc en place, les utilisateurs reçoivent un message d’erreur plus informatif, comme le montrent les figures 4 et 5. Notez qu’en cas d’exception, dataList reste en mode édition. En effet, une fois que l’exception se produit, le flux de contrôle est immédiatement redirigé vers le Catch bloc, contournant le code qui retourne le DataList à son état de pré-édition.

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 en taille réelle)

Un message d’erreur s’affiche lors de la saisie d’un prix négatif

Figure 5 : Un message d’erreur s’affiche lors de la saisie d’un prix négatif (cliquez pour afficher l’image en taille réelle)

Résumé

GridView et ObjectDataSource fournissent des gestionnaires d’événements post-niveau qui incluent des informations sur les exceptions qui ont été déclenchées pendant le flux de travail de mise à jour et de suppression, ainsi que des 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 du DataList et de l’utilisation directe de la BLL. 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 workflow de mise à jour de DataList modifiable en ajoutant un Try ... Catch bloc au gestionnaire d’événements UpdateCommand . 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 !

En savoir plus

Pour plus d’informations sur les sujets abordés dans ce didacticiel, 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 comme consultant indépendant, formateur et écrivain. Son dernier livre est Sams Teach Yourself ASP.NET 2.0 in 24 Hours. Il est accessible à l’adressemitchell@4GuysFromRolla.com . ou via son blog, qui se trouve à l’adresse http://ScottOnWriting.NET.

Remerciements spéciaux à

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