Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
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
Na visão geral de edição e exclusão de dados no tutorial DataList , criamos uma Lista de Dados que oferecia recursos simples de edição e exclusão. Embora totalmente funcional, não foi fácil de usar, pois qualquer erro que ocorreu durante o processo de edição ou exclusão resultou em uma exceção sem tratamento. Por exemplo, omitir o nome do produto ou, ao editar um produto, inserir um valor de preço muito acessível!, gera uma exceção. Como essa exceção não é capturada no código, ela é propagada até o tempo de execução do ASP.NET, que então exibe os detalhes da exceção na página da Web.
Como vimos no tutorial Manipulação de Exceções de BLL e DAL-Level em uma Página ASP.NET, se uma exceção for gerada das camadas profundas 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 com elegância com essas exceções criando manipuladores de eventos para o ObjectDataSource ou para o GridView, verificando uma ocorrência de exceção e, então, indicando que a exceção foi tratada.
Nossos tutoriais do 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 da DAL, precisamos implementar o código de tratamento de exceções no code-behind de nossa página de ASP.NET. Neste tutorial, veremos como lidar com mais tato com exceções geradas durante um fluxo de trabalho de atualização do DataList editável.
Observação
No tutorial Uma Visão Geral de Edição e Exclusão de Dados no tutorial DataList , abordamos diferentes técnicas para editar e excluir dados da Lista de Dados, algumas técnicas envolvidas usando um ObjectDataSource para atualização e exclusão. Se você empregar essas técnicas, poderá lidar com exceções da BLL ou da DAL por meio dos manipuladores de eventos Updated ou Deleted do ObjectDataSource.
Etapa 1: Criando uma Lista de Dados Editável
Antes de nos preocuparmos em lidar com exceções que ocorrem durante o fluxo de trabalho de atualização, vamos primeiro criar uma 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 a classe ProductsBLL com o método GetProducts() para selecionar registros; defina as listas suspensas nas guias INSERT, UPDATE e DELETE como (Nenhum).
Figura 1: retornar as informações do produto usando o GetProducts() método (clique para exibir a imagem em tamanho real)
Depois de concluir o assistente ObjectDataSource, o Visual Studio criará automaticamente um ItemTemplate para o DataList. Substitua isso por um ItemTemplate que exibe o nome e o preço de cada produto e inclui um botão Editar. Em seguida, crie um EditItemTemplate com um controle Web TextBox para nome e preço e botões de Atualizar e Cancelar. Por fim, defina a propriedade DataList como RepeatColumns 2.
Após essas alterações, a marcação declarativa da página deverá ser semelhante à seguinte. Verifique duas vezes para garantir que os botões Editar, Cancelar e Atualizar tenham 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 estar 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 imagem em tamanho real)
Atualmente, o botão Editar apenas causa um postback, mas ainda não torna o produto editável. Para habilitar a edição, precisamos criar manipuladores de eventos para os eventos do DataList EditCommand, CancelCommand e UpdateCommand. Os eventos EditCommand e CancelCommand simplesmente atualizam a propriedade EditItemIndex do DataList e vinculam os dados ao 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();
}
O UpdateCommand manipulador de eventos está um pouco mais envolvido. Ele precisa ler o produto editado da coleção ProductIDDataKeys juntamente com o nome e o preço do produto nos textos das Caixas de Texto EditItemTemplate, e então chamar o método da classe ProductsBLLUpdateProduct antes de retornar a Lista de Dados para seu estado de pré-edição.
Por enquanto, vamos usar exatamente o mesmo código do UpdateCommand manipulador de eventos na visão geral de edição e exclusão de dados no tutorial DataList . Adicionaremos o código para lidar normalmente com exceções na etapa 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();
}
Diante da 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 -US$ 5,00, ou a omissão do nome do produto, uma exceção será gerada. Como o UpdateCommand manipulador de eventos não inclui nenhum código de tratamento de exceção neste momento, a exceção será propagada para o tempo de execução do ASP.NET, 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: Lidando elegantemente com exceções no manipulador de eventos UpdateCommand
Durante o fluxo de trabalho de atualização, as exceções podem ocorrer no UpdateCommand manipulador de eventos, na BLL ou no DAL. Por exemplo, se um usuário inserir um preço muito caro, a Decimal.Parse instrução no UpdateCommand manipulador de eventos gerará 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 de rótulo Web à página cujo atributo ID está configurado como ExceptionDetails. Configure o texto do Rótulo para exibir em fonte vermelha, extra grande, em negrito e em itálico, atribuindo sua propriedade à classe CSS CssClass, que é definida no arquivo Warning.
Quando ocorre um erro, só queremos que o Rótulo seja exibido uma vez. Ou seja, nos postagens de retorno subsequentes, a mensagem de alerta da Etiqueta deve desaparecer. Isso pode ser realizado limpando a propriedade Text do Rótulo ou configurando sua propriedade Visible para False no manipulador de eventos Page_Load (como fizemos anteriormente no tutorial Tratamento de Exceções BLL e DAL-Level em uma Página ASP.NET) ou desabilitando o suporte de estado de visualizaçã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 à propriedade do controle Label ExceptionDetailsText. Como seu estado de exibição está desabilitado, nos postbacks subsequentes, as Text alterações programáticas da propriedade serão perdidas, revertendo de volta 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 UpdateCommand manipulador de eventos. A Try parte contém código que pode levar a uma exceção, enquanto o Catch bloco contém o código executado em face 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 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
}
}
Quando uma exceção de qualquer tipo é gerada por código dentro do bloco Try, o código do bloco Catch começará a ser executado. O tipo de exceção que é gerada DbException, NoNullAllowedExceptione ArgumentExceptionassim 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á gerado. Se um valor ilegal for inserido para os UnitPricecampos, UnitsInStockou UnitsOnOrderReorderLevel campos, um ArgumentException será gerado, pois adicionamos código para validar esses valores de campo na ProductsDataTable 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 em uma forma quase idêntica no tutorial Tratamento de Exceções BLL e DAL-Level em uma página ASP.NET, fornece este nível de detalhe:
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;
}
Para concluir este tutorial, basta chamar o DisplayExceptionDetails método do bloco Catch passando na instância capturada Exception (ex).
Com o Try ... Catch bloco em vigor, os usuários recebem uma mensagem de erro mais informativa, como mostram as Figuras 4 e 5. Observe que, diante de uma exceção, a Lista de Dados permanece no modo de edição. Isso ocorre porque, depois que a exceção ocorre, o fluxo de controle é redirecionado imediatamente para o Catch bloco, ignorando o código que retorna a Lista de Dados para seu estado de pré-edição.
Figura 4: Uma mensagem de erro será exibida se um usuário omitir um campo obrigatório (clique para exibir uma 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 pós-nível 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. No entanto, esses recursos não estão disponíveis ao trabalhar com o DataList e usar a BLL diretamente. Em vez disso, somos responsáveis por implementar o tratamento de exceções.
Neste tutorial, vimos como adicionar o tratamento de exceções a um fluxo de trabalho de atualização do DataList editável adicionando um Try ... Catch bloco ao UpdateCommand manipulador de eventos. Se uma exceção for gerada durante o fluxo de trabalho de atualização, o código do bloco Catch será executado, exibindo informações úteis na ExceptionDetails Etiqueta.
Neste ponto, o DataList não faz nenhum esforço para impedir que exceções ocorram 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 pela entrada inválida do usuário adicionando controles de validação no EditItemTemplate.
Divirta-se programando!
Leitura Adicional
Para obter mais informações sobre os tópicos discutidos neste tutorial, consulte os seguintes recursos:
- Diretrizes de design para exceções
- Módulos e manipuladores de registro de erros (ELMAH) (uma biblioteca de código aberto para registro de erros)
- Biblioteca Empresarial para .NET Framework 2.0 (inclui o Bloco de Aplicativos de Gerenciamento de Exceções)
Sobre o autor
Scott Mitchell, autor de sete livros asp/ASP.NET e fundador da 4GuysFromRolla.com, trabalha com tecnologias da Microsoft Web desde 1998. Scott trabalha como consultor independente, treinador e escritor. Seu último livro é Sams Teach Yourself ASP.NET 2.0 em 24 Horas. Ele pode ser alcançado em mitchell@4GuysFromRolla.com.
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? Se assim for, deixe-me uma linha em mitchell@4GuysFromRolla.com.