Tratar de exceções de nível BLL e DAL (VB)
por Scott Mitchell
Neste tutorial, veremos como lidar com tato com exceções geradas durante o fluxo de trabalho de atualização de um DataList editável.
Introdução
No tutorial Visão geral da edição e exclusão de dados na Lista de dados, criamos uma Lista de dados que oferecia recursos simples de edição e exclusão. Embora totalmente funcional, dificilmente era fácil de usar, pois qualquer erro que ocorresse durante o processo de edição ou exclusão resultava em uma exceção não tratada. Por exemplo, omitir o nome do produto ou, ao editar um produto, inserir um valor de preço de Muito acessível!, gera uma exceção. Como essa exceção não é capturada no código, ela se espalha para o runtime ASP.NET, que exibe os detalhes da exceção na página da Web.
Como vimos no tutorial Manipulando exceções de nível BLL e DAL em uma página ASP.NET, se uma exceção for gerada das profundezas da Lógica de Negócios ou das Camadas de Acesso a Dados, os detalhes da exceção serão retornados para o ObjectDataSource e, em seguida, para o GridView. Vimos como lidar normalmente com essas exceções criando Updated
manipuladores de eventos para RowUpdated
o ObjectDataSource ou GridView, verificando se há uma exceção e, em seguida, indicando que a exceção foi tratada.
Nossos tutoriais DataList, no entanto, não estão usando o ObjectDataSource para atualizar e excluir dados. Em vez disso, estamos trabalhando diretamente contra a BLL. Para detectar exceções originadas da BLL ou DAL, precisamos implementar o código de tratamento de exceções no code-behind de nossa página ASP.NET. Neste tutorial, veremos como lidar com mais tato com exceções geradas durante um fluxo de trabalho de atualização editável do DataList.
Observação
No tutorial Uma visão geral da edição e exclusão de dados na lista de dados, discutimos diferentes técnicas para editar e excluir dados da lista de dados, algumas técnicas envolvidas no uso de um ObjectDataSource para atualizar e excluir. Se você empregar essas técnicas, poderá lidar com exceções da BLL ou DAL por meio do ObjectDataSource s Updated
ou Deleted
manipuladores de eventos.
Etapa 1: Criando uma lista de dados editável
Antes de nos preocuparmos com o tratamento de exceções que ocorrem durante o fluxo de trabalho de atualização, vamos primeiro criar um DataList editável. Abra a ErrorHandling.aspx
página na EditDeleteDataList
pasta, adicione um DataList ao Designer, defina sua ID
propriedade como Products
e adicione um novo ObjectDataSource chamado ProductsDataSource
. Configure o ObjectDataSource para usar o ProductsBLL
método da classe para GetProducts()
selecionar registros; defina as listas suspensas nas guias INSERT, UPDATE e DELETE como (Nenhum).
Figura 1: Retornar as informações do produto usando o método (clique para exibir a GetProducts()
imagem em tamanho real)
Depois de concluir o assistente ObjectDataSource, o Visual Studio criará automaticamente um ItemTemplate
para o DataList. Substitua-o por um ItemTemplate
que exiba o nome e o preço de cada produto e inclua um botão Editar. Em seguida, crie um EditItemTemplate
com um controle Web TextBox para nome e preço e botões Atualizar e Cancelar. Por fim, defina a DataList propriedade como RepeatColumns
2.
Após essas alterações, a marcação declarativa da página deve ser semelhante à seguinte. Verifique novamente se os botões Editar, Cancelar e Atualizar têm suas CommandName
propriedades definidas como Editar, Cancelar e Atualizar, respectivamente.
<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>
Observação
Para este tutorial, o estado de exibição do DataList deve ser habilitado.
Reserve um momento para ver nosso progresso por meio de um navegador (consulte a Figura 2).
Figura 2: Cada produto inclui um botão Editar (clique para exibir a imagem em tamanho real)
Atualmente, o botão Editar só causa um postback, ele ainda não torna o produto editável. Para habilitar a edição, precisamos criar manipuladores de eventos para os DataList s EditCommand
, CancelCommand
, e eventos UpdateCommand
. Os EditCommand
eventos and CancelCommand
simplesmente atualizam a DataList propriedade e EditItemIndex
reassociam os dados ao 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
O UpdateCommand
manipulador de eventos é um pouco mais envolvido. Ele precisa ler o produto editado DataKeys
da ProductID
coleção junto com o nome e o preço do produto das TextBoxes no EditItemTemplate
, e chamar o ProductsBLL
método da classe antes UpdateProduct
de retornar o DataList ao seu estado de pré-edição.
Por enquanto, vamos usar exatamente o mesmo código do manipulador de UpdateCommand
eventos na Visão geral da edição e exclusão de dados no tutorial DataList . Adicionaremos o código para lidar normalmente com exceções na etapa 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
Diante de uma entrada inválida que pode estar na forma de um preço unitário formatado incorretamente, um valor de preço unitário ilegal como -$ 5,00 ou a omissão do nome do produto, uma exceção será levantada. Como o manipulador de UpdateCommand
eventos não inclui nenhum código de tratamento de exceção neste momento, a exceção será propagada até o ASP.NET tempo de execução, onde será exibida para o usuário final (consulte a Figura 3).
Figura 3: Quando ocorre uma exceção sem tratamento, o usuário final vê uma página de erro
Etapa 2: Manipulando exceções normalmente no manipulador de eventos UpdateCommand
Durante o fluxo de trabalho de atualização, podem ocorrer exceções no manipulador de UpdateCommand
eventos, na BLL ou no DAL. Por exemplo, se um usuário inserir um preço de Muito caro, a Decimal.Parse
instrução no UpdateCommand
manipulador de eventos lançará uma FormatException
exceção. Se o usuário omitir o nome do produto ou se o preço tiver um valor negativo, o DAL gerará uma exceção.
Quando ocorre uma exceção, queremos exibir uma mensagem informativa dentro da própria página. Adicione um controle Web Label à página definida ID
como ExceptionDetails
. Configure o texto do rótulo para ser exibido em uma fonte vermelha, extragrande, negrito e itálico atribuindo sua CssClass
propriedade à Warning
classe CSS, que é definida no Styles.css
arquivo.
Quando ocorre um erro, queremos que o rótulo seja exibido apenas uma vez. Ou seja, em postbacks subsequentes, a mensagem de aviso do Label deve desaparecer. Isso pode ser feito limpando a propriedade do Rótulo Text
ou definindo sua Visible
propriedade como False
no Page_Load
manipulador de eventos (como fizemos no tutorial Manipulando exceções de nível BLL e DAL em uma página ASP.NET) ou desabilitando o suporte ao estado de exibição do Rótulo. Vamos usar a última opção.
<asp:Label ID="ExceptionDetails" EnableViewState="False" CssClass="Warning"
runat="server" />
Quando uma exceção for gerada, atribuiremos os detalhes da exceção à ExceptionDetails
propriedade do Text
controle Label. Como seu estado de exibição está desabilitado, em postbacks subsequentes, as alterações programáticas da Text
propriedade serão perdidas, revertendo para o texto padrão (uma cadeia de caracteres vazia), ocultando assim a mensagem de aviso.
Para determinar quando um erro foi gerado para exibir uma mensagem útil na página, precisamos adicionar um Try ... Catch
bloco ao manipulador de UpdateCommand
eventos. A Try
parte contém código que pode levar a uma exceção, enquanto o Catch
bloco contém código que é executado diante de uma exceção. Confira a seção Conceitos básicos de tratamento de exceções na documentação do .NET Framework para obter mais informações sobre o Try ... Catch
bloco.
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 uma exceção de qualquer tipo é gerada pelo código dentro do Try
bloco, o Catch
código do bloco começará a ser executado. O tipo de exceção que é lançada DbException
, NoNullAllowedException
, ArgumentException
, e assim por diante depende do que, exatamente, precipitou o erro em primeiro lugar. Se houver um problema no nível do banco de dados, um DbException
será lançado. Se um valor ilegal for inserido para os UnitPrice
campos , UnitsInStock
, UnitsOnOrder
, ou ReorderLevel
, ArgumentException
um será lançado, pois adicionamos código para validar esses valores de ProductsDataTable
campo na classe (consulte o tutorial Criando uma Camada Lógica de Negócios ).
Podemos fornecer uma explicação mais útil para o usuário final baseando o texto da mensagem no tipo de exceção capturada. O código a seguir, que foi usado de forma quase idêntica no tutorial Manipulando exceções de nível BLL e DAL em uma página de ASP.NET, fornece esse nível de detalhe:
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
Para concluir este tutorial, basta chamar o DisplayExceptionDetails
método do Catch
bloco que passa na instância capturada Exception
(ex
).
Com o bloco instalado, os usuários recebem uma mensagem de erro mais informativa, como mostram as Try ... Catch
Figuras 4 e 5. Observe que, diante de uma exceção, o DataList permanece no modo de edição. Isso ocorre porque, uma vez que a exceção ocorre, o fluxo de controle é imediatamente redirecionado para o Catch
bloco, ignorando o código que retorna o DataList ao seu estado de pré-edição.
Figura 4: Uma mensagem de erro é exibida se um usuário omitir um campo obrigatório (clique para exibir a imagem em tamanho real)
Figura 5: Uma mensagem de erro é exibida ao inserir um preço negativo (clique para exibir a imagem em tamanho real)
Resumo
O GridView e o ObjectDataSource fornecem manipuladores de eventos de nível posterior que incluem informações sobre quaisquer exceções que foram geradas durante o fluxo de trabalho de atualização e exclusão, bem como propriedades que podem ser definidas para indicar se a exceção foi tratada ou não. Esses recursos, no entanto, não estão disponíveis ao trabalhar com a DataList e usar a BLL diretamente. Em vez disso, somos responsáveis por implementar o tratamento de exceções.
Neste tutorial, vimos como adicionar tratamento de exceção a um fluxo de trabalho de atualização editável do DataList adicionando um Try ... Catch
bloco ao manipulador de UpdateCommand
eventos. Se uma exceção for gerada durante o fluxo de trabalho de atualização, o Catch
código do bloco será executado, exibindo informações úteis no ExceptionDetails
Rótulo.
Neste ponto, o DataList não faz nenhum esforço para evitar que exceções aconteçam em primeiro lugar. Embora saibamos que um preço negativo resultará em uma exceção, ainda não adicionamos nenhuma funcionalidade para impedir proativamente que um usuário insira essa entrada inválida. Em nosso próximo tutorial, veremos como ajudar a reduzir as exceções causadas por entradas de usuário inválidas adicionando controles de validação no EditItemTemplate
.
Boa programação!
Leitura Adicional
Para obter mais informações sobre os tópicos discutidos neste tutorial, consulte os seguintes recursos:
- Diretrizes de design para exceções
- ELMAH (Error Logging Modules and Handlers) (uma biblioteca de software livre para erros de log)
- Enterprise Library for .NET Framework 2.0 (inclui o Exception Management Application Block)
Sobre o autor
Scott Mitchell, autor de sete livros ASP/ASP.NET e fundador da 4GuysFromRolla.com, trabalha com tecnologias da Web da Microsoft desde 1998. Scott trabalha como consultor, instrutor e escritor independente. Seu último livro é Sams Teach Yourself ASP.NET 2.0 em 24 horas. Ele pode ser contatado em mitchell@4GuysFromRolla.com. ou através de seu blog, que pode ser encontrado em http://ScottOnWriting.NET.
Agradecimentos especiais a
Esta série de tutoriais foi revisada por muitos revisores úteis. O revisor principal deste tutorial foi Ken Pespisa. Interessado em revisar meus próximos artigos do MSDN? Em caso afirmativo, envie-me uma mensagem para mitchell@4GuysFromRolla.com.