Zpracování výjimek na úrovni knihoven BLL a DAL (C#)

Scott Mitchell

Stáhnout PDF

V tomto kurzu se dozvíte, jak taktně zpracovat výjimky vyvolané během pracovního postupu aktualizace upravitelného seznamu dat.

Úvod

V kurzu Přehled úprav a odstranění dat v části DataList jsme vytvořili soubor DataList, který nabízí jednoduché možnosti úprav a odstranění. I když byl plně funkční, nebyl téměř uživatelsky přívětivý, protože jakákoli chyba, ke které došlo během procesu úprav nebo odstraňování, způsobila neošetřenou výjimku. Pokud například vynecháte název produktu nebo při úpravě produktu zadáte hodnotu ceny Velmi dostupné!, vyvolá se výjimka. Vzhledem k tomu, že tato výjimka není zachycena v kódu, přejde do ASP.NET modulu runtime, který pak na webové stránce zobrazí podrobnosti o výjimce.

Jak jsme viděli v kurzu Zpracování výjimek BLL a DAL-Level v kurzu ASP.NET Page , pokud je výjimka vyvolána z hloubky vrstvy obchodní logiky nebo přístupu k datům, podrobnosti o výjimce se vrátí do ObjectDataSource a pak do objektu GridView. Viděli jsme, jak tyto výjimky řádně zpracovat vytvořením UpdatedRowUpdated obslužných rutin nebo událostí pro objekt ObjectDataSource nebo GridView, kontrolou výjimky a následným označením, že byla výjimka zpracována.

Naše kurzy DataList ale nepoužívají ObjectDataSource k aktualizaci a odstraňování dat. Místo toho pracujeme přímo proti BLL. Abychom mohli detekovat výjimky pocházející z BLL nebo DAL, musíme implementovat kód zpracování výjimek v kódu na pozadí naší ASP.NET stránky. V tomto kurzu se dozvíte, jak taktněji zpracovávat výjimky vyvolané během upravitelného pracovního postupu aktualizace seznamu dat.

Poznámka

V kurzu Přehled úprav a odstranění dat v části DataList jsme probrali různé techniky pro úpravu a odstranění dat z objektu DataList. Některé techniky zahrnovaly použití objectDataSource pro aktualizaci a odstranění. Pokud použijete tyto techniky, můžete zpracovávat výjimky z BLL nebo DAL prostřednictvím ObjectDataSource s Updated nebo Deleted obslužných rutin událostí.

Krok 1: Vytvoření upravitelného seznamu dat

Než se začneme zabývat zpracováním výjimek, ke kterým dochází během aktualizace pracovního postupu, pojďme nejprve vytvořit upravitelný seznam DataList. ErrorHandling.aspx Otevřete stránku ve EditDeleteDataList složce , přidejte do Designer DataList, nastavte jeho ID vlastnost na Productsa přidejte nový ObjectDataSource s názvem ProductsDataSource. Nakonfigurujte ObjectDataSource tak, aby používal metodu ProductsBLL třídy s GetProducts() pro výběr záznamů; nastavte rozevírací seznamy na kartách INSERT, UPDATE a DELETE na (None).

Vrácení informací o produktu pomocí metody GetProducts()

Obrázek 1: Vrácení informací o produktu pomocí GetProducts() metody (kliknutím zobrazíte obrázek v plné velikosti)

Po dokončení průvodce ObjectDataSource visual Studio automaticky vytvoří objekt ItemTemplate pro dataList. Nahraďte ho kódem ItemTemplate , který zobrazuje název a cenu každého produktu a obsahuje tlačítko Upravit. Dále vytvořte s webovým ovládacím EditItemTemplate prvku TextBox pro název a cenu a tlačítka Update a Cancel. Nakonec nastavte vlastnost DataList na RepeatColumns hodnotu 2.

Po těchto změnách by deklarativní kód stránky měl vypadat nějak takto. Pečlivě zkontrolujte, jestli mají CommandName tlačítka Upravit, Zrušit a Aktualizovat nastavené vlastnosti na Upravit, Zrušit a Aktualizovat.

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

Poznámka

Pro účely tohoto kurzu musí být povolený stav zobrazení DataList.

Podívejte se na průběh v prohlížeči (viz Obrázek 2).

Každý produkt obsahuje tlačítko Upravit.

Obrázek 2: Každý produkt obsahuje tlačítko Upravit (kliknutím zobrazíte obrázek v plné velikosti)

Tlačítko Upravit v současné době způsobuje pouze zpětné odeslání, které ještě neumožňuje upravovat produkt. Pokud chcete povolit úpravy, musíme vytvořit obslužné rutiny událostí pro události DataList s EditCommand, CancelCommanda UpdateCommand . Události EditCommand a CancelCommand jednoduše aktualizují vlastnost DataList s EditItemIndex a předají data na 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();
}

Obslužná rutina UpdateCommand události je trochu více zapojená. Musí přečíst upravené produkty ProductID z DataKeys kolekce spolu s názvem produktu a cenou z textových polí v EditItemTemplatea potom zavolat metodu ProductsBLL třídy s UpdateProduct před vrácením DataList do stavu předběžné úpravy.

Prozatím použijeme přesně stejný kód z UpdateCommand obslužné rutiny události v kurzu Přehled úprav a odstranění dat v části DataList . V kroku 2 přidáme kód pro řádné zpracování výjimek.

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

V případě neplatného vstupu, který může mít podobu nesprávně naformátované jednotkové ceny, neplatné hodnoty jednotkové ceny jako -5,00 Usd nebo vynechání názvu produktu, bude vyvolána výjimka. UpdateCommand Vzhledem k tomu, že obslužná rutina události v tomto okamžiku neobsahuje žádný kód zpracování výjimek, výjimka se zobrazí až do ASP.NET modulu runtime, kde se zobrazí koncovému uživateli (viz obrázek 3).

Když dojde k neošetřené výjimce, koncovému uživateli se zobrazí chybová stránka.

Obrázek 3: Když dojde k neošetřené výjimce, koncovému uživateli se zobrazí chybová stránka

Krok 2: Řádné zpracování výjimek v obslužné rutině události UpdateCommand

Během aktualizace pracovního postupu může dojít k výjimkám v obslužné rutině UpdateCommand události, BLL nebo DAL. Například pokud uživatel zadá cenu Příliš drahé, Decimal.Parse příkaz v obslužné rutině UpdateCommand události vyvolá FormatException výjimku. Pokud uživatel vynechá název produktu nebo pokud cena má zápornou hodnotu, dal vyvolá výjimku.

Když dojde k výjimce, chceme na samotné stránce zobrazit informativní zprávu. Přidejte na stránku ovládací prvek Label Web, který ID je nastavený na ExceptionDetails. Nakonfigurujte text Label s tak, aby se zobrazoval červeně, velmi velkým tučným písmem a kurzívou tím, že přiřadíte jeho CssClass vlastnost třídě Warning CSS, která je definovaná v Styles.css souboru.

Když dojde k chybě, chceme, aby se popisek zobrazil jenom jednou. To znamená, že při následných zpětných odesláních by zpráva Upozornění na popisek měla zmizet. Toho lze dosáhnout buď vymazáním vlastnosti Label s Text , nebo nastavením její Visible vlastnosti na False hodnotu v Page_Load obslužné rutině události (jak jsme to udělali v kurzu Zpracování výjimek BLL a DAL-Level na ASP.NET stránce ) nebo zakázáním podpory stavu zobrazení popisků. Použijeme druhou možnost.

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

Při vyvolání výjimky přiřadíme podrobnosti o výjimce vlastnosti ExceptionDetails ovládacího prvku Text Popisek. Vzhledem k tomu, že je jeho stav zobrazení zakázán, při následných postbackech Text dojde ke ztrátě programových změn vlastností a vrátí se zpět na výchozí text (prázdný řetězec), čímž se zpráva upozornění skryje.

Abychom zjistili, kdy byla vyvolána chyba, aby se na stránce zobrazila užitečná zpráva, musíme do UpdateCommand obslužné Try ... Catch rutiny události přidat blok. Část Try obsahuje kód, který může vést k výjimce, zatímco Catch blok obsahuje kód, který se provádí tváří v tvář výjimce. Další informace Try ... Catch o tomto bloku najdete v části Základy zpracování výjimek v dokumentaci k rozhraní .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
    }
}

Pokud kód v rámci Try bloku vyvolá výjimku libovolného typu, Catch kód bloku se začne spouštět. Typ výjimky, která je vyvolán DbException, NoNullAllowedException, ArgumentExceptionatd., závisí na tom, co přesně na prvním místě vyvolalo chybu. Pokud dojde k problému na úrovni databáze, DbException vyvolá se . Pokud je pro UnitPricepole , , UnitsInStockUnitsOnOrdernebo ReorderLevel zadána neplatná hodnota, ArgumentException vyvolá se chyba , protože jsme přidali kód pro ověření těchto hodnot polí ve ProductsDataTable třídě (viz kurz Vytvoření vrstvy obchodní logiky).

Můžeme koncovému uživateli poskytnout užitečnější vysvětlení tím, že text zprávy zadáme na typu zachycené výjimky. Následující kód, který byl použit v téměř identické podobě v kurzu Zpracování výjimek BLL a DAL-Level v ASP.NET Page , poskytuje tuto úroveň podrobností:

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

K dokončení tohoto kurzu jednoduše zavolejte metodu DisplayExceptionDetails z bloku, který Catch předává zachycenou Exception instanci (ex).

Se zavedeným Try ... Catch blokem se uživatelům zobrazí informativnější chybová zpráva, jak ukazují obrázky 4 a 5. Všimněte si, že tváří v tvář výjimce zůstává Seznam dat v režimu úprav. Je to proto, že jakmile dojde k výjimce, tok řízení je okamžitě přesměrován na Catch blok a obejde kód, který vrací dataList do stavu předběžné úpravy.

Pokud uživatel vynechá povinné pole, zobrazí se chybová zpráva.

Obrázek 4: Pokud uživatel vynechá povinné pole, zobrazí se chybová zpráva (kliknutím zobrazíte obrázek v plné velikosti).

Při zadávání záporné ceny se zobrazí chybová zpráva.

Obrázek 5: Při zadání záporné ceny se zobrazí chybová zpráva (kliknutím zobrazíte obrázek v plné velikosti)

Souhrn

GridView a ObjectDataSource poskytují obslužné rutiny událostí po úrovni, které obsahují informace o všech výjimkách, které byly vyvolány během aktualizace a odstraňování pracovního postupu, stejně jako vlastnosti, které lze nastavit tak, aby indikovaly, zda byla výjimka zpracována. Tyto funkce však nejsou k dispozici při práci se seznamem DataList a při přímém použití BLL. Místo toho zodpovídáme za implementaci zpracování výjimek.

V tomto kurzu jsme viděli, jak přidat zpracování výjimek do upravitelného pracovního postupu aktualizace DataList přidáním Try ... Catch bloku do obslužné UpdateCommand rutiny události. Pokud je během aktualizace pracovního postupu vyvolána výjimka, Catch spustí se kód bloku s a zobrazí se užitečné informace v popisku ExceptionDetails .

V tomto okamžiku datový seznam nevydělá žádné úsilí, aby zabránil výjimkám na prvním místě. I když víme, že záporná cena bude mít za následek výjimku, zatím jsme nepřidali žádnou funkci, která by proaktivně zabránila uživateli v zadání takového neplatného vstupu. V dalším kurzu se dozvíte, jak omezit výjimky způsobené neplatným uživatelským vstupem přidáním ověřovacích ovládacích prvků do EditItemTemplate.

Všechno nejlepší na programování!

Další čtení

Další informace o tématech probíraných v tomto kurzu najdete v následujících zdrojích informací:

O autorovi

Scott Mitchell, autor sedmi knih o ASP/ASP.NET a zakladatel 4GuysFromRolla.com, pracuje s webovými technologiemi Microsoftu od roku 1998. Scott pracuje jako nezávislý konzultant, školitel a spisovatel. Jeho nejnovější kniha je Sams Teach Yourself ASP.NET 2.0 in 24 Hours. Můžete ho zastihnout na mitchell@4GuysFromRolla.comadrese . nebo prostřednictvím jeho blogu, který najdete na adrese http://ScottOnWriting.NET.

Zvláštní poděkování

Tato série kurzů byla zkontrolována mnoha užitečnými recenzenty. Hlavním revidujícím pro tento kurz byl Ken Pespisa. Chtěli byste si projít své nadcházející články na webu MSDN? Pokud ano, dejte mi řádek na mitchell@4GuysFromRolla.com.