Udostępnij za pośrednictwem


Obsługa wyjątków na poziomie warstwy logiki biznesowej i warstwy dostępu do danych (C#)

Autor: Scott Mitchell

Pobierz plik PDF

W tym samouczku zobaczymy, jak tactfully obsługiwać wyjątki zgłaszane podczas edytowalnego przepływu pracy aktualizacji elementu DataList.

Wprowadzenie

W samouczku Przegląd edytowania i usuwania danych w usłudze DataList utworzyliśmy listę danych, która oferuje proste możliwości edytowania i usuwania. Chociaż w pełni funkcjonalne, nie było to przyjazne dla użytkownika, ponieważ każdy błąd, który wystąpił podczas edytowania lub usuwania procesu, spowodował nieobsługiwany wyjątek. Na przykład pominięcie nazwy produktu lub, podczas edytowania produktu, wprowadzenie wartości ceny bardzo przystępnej!, zgłasza wyjątek. Ponieważ ten wyjątek nie jest przechwytywane w kodzie, bąbelki do środowiska uruchomieniowego ASP.NET, który następnie wyświetla szczegóły wyjątku na stronie internetowej.

Jak pokazano w samouczku Obsługa BLL i DAL-Level Wyjątki na stronie ASP.NET , jeśli zostanie zgłoszony wyjątek z głębi warstwy logiki biznesowej lub dostępu do danych, szczegóły wyjątku zostaną zwrócone do obiektu ObjectDataSource, a następnie do kontrolki GridView. Zobaczyliśmy, jak bezpiecznie obsługiwać te wyjątki, tworząc Updated programy obsługi zdarzeń dla RowUpdated obiektu ObjectDataSource lub GridView, sprawdzając wyjątek, a następnie wskazując, że wyjątek został obsłużony.

Nasze samouczki dataList nie używają jednak obiektu ObjectDataSource do aktualizowania i usuwania danych. Zamiast tego pracujemy bezpośrednio przeciwko BLL. Aby wykryć wyjątki pochodzące z biblioteki BLL lub DAL, musimy zaimplementować kod obsługi wyjątków w kodzie naszej strony ASP.NET. W tym samouczku zobaczymy, jak bardziej tactfully obsługiwać wyjątki zgłaszane podczas edytowalnego przepływu pracy aktualizacji elementu DataList.

Uwaga

W samouczku Omówienie edytowania i usuwania danych w usłudze DataList omówiliśmy różne techniki edytowania i usuwania danych z listy DataList, niektóre techniki związane z używaniem obiektu ObjectDataSource do aktualizowania i usuwania. Jeśli używasz tych technik, możesz obsługiwać wyjątki z biblioteki BLL lub DAL za pośrednictwem programów obsługi zdarzeń lub Deleted obiektów ObjectDataSourceUpdated.

Krok 1. Tworzenie edytowalnej listy danych

Zanim martwimy się o obsługę wyjątków występujących podczas aktualizowania przepływu pracy, najpierw utwórzmy edytowalną listę danych. ErrorHandling.aspx Otwórz stronę w folderzeEditDeleteDataList, dodaj listę danych do Projektant, ustaw jej ID właściwość na Products, a następnie dodaj nową właściwość ObjectDataSource o nazwie ProductsDataSource. Skonfiguruj obiekt ObjectDataSource do używania ProductsBLL metody klasy s GetProducts() do wybierania rekordów; ustaw listy rozwijane na kartach INSERT, UPDATE i DELETE na wartość (Brak).

Zwracanie informacji o produkcie przy użyciu metody GetProducts()

Rysunek 1. Zwracanie informacji o produkcie GetProducts() przy użyciu metody (kliknij, aby wyświetlić obraz pełnowymiarowy)

Po ukończeniu pracy kreatora ObjectDataSource program Visual Studio automatycznie utworzy obiekt ItemTemplate dataList. Zastąp element nazwą i ceną ItemTemplate każdego produktu, który zawiera przycisk Edytuj. Następnie utwórz element EditItemTemplate z kontrolką sieci Web TextBox dla nazw i cen oraz przycisków Aktualizuj i Anuluj. Na koniec ustaw właściwość DataList na RepeatColumns 2.

Po tych zmianach znaczniki deklaratywne strony powinny wyglądać podobnie do poniższych. Sprawdź dwukrotnie, aby upewnić się, że przyciski Edytuj, Anuluj i Aktualizuj mają ich CommandName właściwości ustawione odpowiednio na Wartość Edytuj, Anuluj i Aktualizuj.

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

Uwaga

W tym samouczku musi być włączony stan widoku DataList.

Poświęć chwilę, aby wyświetlić postęp w przeglądarce (zobacz Rysunek 2).

Każdy produkt zawiera przycisk edycji

Rysunek 2. Każdy produkt zawiera przycisk edycji (kliknij, aby wyświetlić obraz pełnowymiarowy)

Obecnie przycisk Edytuj powoduje tylko powrót, który jeszcze nie umożliwia edycji produktu. Aby włączyć edytowanie, musimy utworzyć programy obsługi zdarzeń dla zdarzeń dataList s EditCommand, CancelCommandi UpdateCommand zdarzeń. Zdarzenia EditCommand i CancelCommand po prostu aktualizują właściwość DataList EditItemIndex i ponownie połączyć dane z listy 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();
}

Procedura UpdateCommand obsługi zdarzeń jest nieco bardziej zaangażowana. Należy odczytać w edytowanych produktach ProductID z DataKeys kolekcji wraz z nazwą i ceną produktu z pola TextBoxes w elemecie EditItemTemplate, a następnie wywołać ProductsBLL metodę klasy s UpdateProduct przed zwróceniem elementu DataList do stanu wstępnej edycji.

Na razie użyjmy dokładnie tego samego kodu z UpdateCommand programu obsługi zdarzeń w samouczku Przegląd edytowania i usuwania danych w samouczku DataList . Dodamy kod, aby bezpiecznie obsługiwać wyjątki w kroku 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();
}

W obliczu nieprawidłowych danych wejściowych, które mogą być w postaci nieprawidłowo sformatowanej ceny jednostkowej, zostanie podniesiona nieprawidłowa wartość ceny jednostkowej, na przykład -5,00 USD lub pominięcie nazwy produktu. UpdateCommand Ponieważ program obsługi zdarzeń nie zawiera żadnego kodu obsługi wyjątków w tym momencie, wyjątek będzie bąbelkować do środowiska uruchomieniowego ASP.NET, gdzie będzie wyświetlany użytkownikowi końcowemu (patrz Rysunek 3).

Gdy wystąpi nieobsługiwany wyjątek, użytkownik końcowy zobaczy stronę błędu

Rysunek 3. Po wystąpieniu nieobsługiwanego wyjątku użytkownik końcowy widzi stronę błędu

Krok 2. Bezproblemowa obsługa wyjątków w procedurze obsługi zdarzeń UpdateCommand

Podczas aktualizowania przepływu pracy wyjątki mogą wystąpić w UpdateCommand procedurze obsługi zdarzeń, BLL lub DAL. Jeśli na przykład użytkownik wprowadzi cenę Za drogie, Decimal.Parse instrukcja w procedurze UpdateCommand obsługi zdarzeń zgłosi FormatException wyjątek. Jeśli użytkownik pomija nazwę produktu lub jeśli cena ma wartość ujemną, dal zgłosi wyjątek.

Gdy wystąpi wyjątek, chcemy wyświetlić komunikat informacyjny w samej stronie. Dodaj kontrolkę Etykieta sieci Web do strony, której ID ustawiono wartość ExceptionDetails. Skonfiguruj tekst Etykiety, aby był wyświetlany w kolorze czerwonym, bardzo dużym, pogrubionym i kursywym, przypisując jej CssClass właściwość do Warning klasy CSS, która jest zdefiniowana w Styles.css pliku.

Gdy wystąpi błąd, chcemy, aby etykieta będzie wyświetlana tylko raz. Oznacza to, że w kolejnych postbackach komunikat ostrzegawczy Etykieta powinien zniknąć. Można to osiągnąć przez wyczyszczenie właściwości Etykieta Text lub ustawienia jej Visible właściwości w FalsePage_Load programie obsługi zdarzeń (podobnie jak w przypadku obsługi BLL i DAL-Level Wyjątki w samouczku dotyczącym strony ASP.NET ) lub przez wyłączenie obsługi stanu widoku etykiety. Użyjmy tej drugiej opcji.

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

Po wystąpieniu wyjątku przypiszemy szczegóły wyjątku do ExceptionDetails właściwości kontrolki Etykieta Text . Ponieważ jego stan widoku jest wyłączony, po kolejnych postbackach Text zmiany programowe właściwości zostaną utracone, cofając się do domyślnego tekstu (pustego ciągu), ukrywając w ten sposób komunikat ostrzegawczy.

Aby określić, kiedy został zgłoszony błąd, aby wyświetlić pomocny komunikat na stronie, musimy dodać Try ... Catch blok do programu obsługi zdarzeń UpdateCommand . Część Try zawiera kod, który może prowadzić do wyjątku, podczas gdy Catch blok zawiera kod wykonywany w obliczu wyjątku. Zapoznaj się z sekcją Podstawy obsługi wyjątków w dokumentacji .NET Framework, aby uzyskać więcej informacji na Try ... Catch temat bloku.

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

Gdy wyjątek dowolnego typu jest zgłaszany przez kod w Try bloku, Catch kod bloku rozpocznie wykonywanie. Typ wyjątku, który jest zgłaszany DbException, NoNullAllowedException, ArgumentExceptioni tak dalej zależy od tego, co dokładnie, wytrąciło błąd w pierwszej kolejności. Jeśli wystąpi problem na poziomie bazy danych, DbException zostanie zgłoszony błąd. Jeśli dla pól , , UnitsInStocklub UnitsOnOrderReorderLevel zostanie wprowadzona UnitPriceniedozwolona wartość, ArgumentException zostanie zgłoszony kod, ponieważ dodaliśmy kod w celu zweryfikowania tych wartości pól w ProductsDataTable klasie (zobacz samouczek Tworzenie warstwy logiki biznesowej).

Możemy podać bardziej przydatne wyjaśnienie użytkownikowi końcowemu, opierając tekst wiadomości na typie przechwyconego wyjątku. Poniższy kod, który został użyty w niemal identycznym formularzu z powrotem w samouczku Obsługa BLL i DAL-Level Wyjątki na stronie ASP.NET zawiera ten poziom szczegółów:

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

Aby ukończyć ten samouczek, po prostu wywołaj metodę DisplayExceptionDetails z Catch bloku przekazującego w przechwyconym Exception wystąpieniu (ex).

Po zablokowaniu Try ... Catch użytkownicy są wyświetlani z bardziej informacyjnym komunikatem o błędzie, jak pokazano na rysunkach 4 i 5. Należy pamiętać, że w obliczu wyjątku lista danych pozostaje w trybie edycji. Dzieje się tak dlatego, że po wystąpieniu wyjątku przepływ sterowania jest natychmiast przekierowywany do Catch bloku, pomijając kod, który zwraca wartość DataList do stanu przed edycją.

Komunikat o błędzie jest wyświetlany, jeśli użytkownik pomija wymagane pole

Rysunek 4. Komunikat o błędzie jest wyświetlany, jeśli użytkownik pomija wymagane pole (kliknij, aby wyświetlić obraz pełnowymiarowy)

Komunikat o błędzie jest wyświetlany podczas wprowadzania ujemnej ceny

Rysunek 5. Komunikat o błędzie jest wyświetlany podczas wprowadzania ceny ujemnej (kliknij, aby wyświetlić obraz pełnowymiarowy)

Podsumowanie

Kontrolka GridView i ObjectDataSource udostępniają programy obsługi zdarzeń po poziomie, które zawierają informacje o wszelkich wyjątkach zgłoszonych podczas aktualizowania i usuwania przepływu pracy, a także właściwości, które można ustawić, aby wskazać, czy wyjątek został obsłużony. Te funkcje są jednak niedostępne podczas pracy z listą DataList i bezpośrednio przy użyciu biblioteki BLL. Zamiast tego jesteśmy odpowiedzialni za implementację obsługi wyjątków.

W tym samouczku pokazano, jak dodać obsługę wyjątków do edytowalnego przepływu pracy aktualizacji elementu DataList przez dodanie Try ... Catch bloku do procedury obsługi zdarzeń UpdateCommand . Jeśli podczas aktualizowania przepływu pracy zostanie zgłoszony wyjątek, Catch kod bloku jest wykonywany, wyświetlając przydatne informacje w etykiecie ExceptionDetails .

W tym momencie lista Danych Nie podejmuje żadnych starań, aby zapobiec wystąpieniu wyjątków w pierwszej kolejności. Mimo że wiemy, że cena ujemna spowoduje wyjątek, nie dodaliśmy jeszcze żadnych funkcji, aby aktywnie uniemożliwić użytkownikowi wprowadzanie takich nieprawidłowych danych wejściowych. W następnym samouczku zobaczymy, jak zmniejszyć wyjątki spowodowane nieprawidłowymi danymi wejściowymi użytkownika przez dodanie kontrolek walidacji w elemecie EditItemTemplate.

Szczęśliwe programowanie!

Dalsze informacje

Aby uzyskać więcej informacji na temat tematów omówionych w tym samouczku, zapoznaj się z następującymi zasobami:

Informacje o autorze

Scott Mitchell, autor siedmiu książek ASP/ASP.NET i założyciel 4GuysFromRolla.com, współpracuje z technologiami internetowymi firmy Microsoft od 1998 roku. Scott pracuje jako niezależny konsultant, trener i pisarz. Jego najnowsza książka to Sams Teach Yourself ASP.NET 2.0 w ciągu 24 godzin. Można do niego dotrzeć pod adresem mitchell@4GuysFromRolla.com. Lub za pośrednictwem swojego bloga, który można znaleźć na stronie http://ScottOnWriting.NET.

Specjalne podziękowania

Ta seria samouczków została sprawdzona przez wielu pomocnych recenzentów. Główny recenzent tego samouczka był Ken Pespisa. Chcesz przejrzeć nadchodzące artykuły MSDN? Jeśli tak, upuść mi wiersz pod adresem mitchell@4GuysFromRolla.com.