ASP .NET - Web Forms Tratando erros


O tratamento de erros e fundamental para que sua aplicação seja gerenciada. Sem isso você fica a mercê do acaso e não sabe como proceder quando coisas inesperadas ocorrem em sua aplicação. Eleve isso ao quadrado quando sua aplicação é uma aplicação web.

Neste artigo vou traçar uma estratégia básica para tratamento de erros em aplicações ASP .NET Web Forms, sim porque para ASP .NET MVC o caminho é diferente.

1 - Tratando erro no nível de métodos

a- Se os erros potenciais são recuperáveis na rotina

Utilize uma combinação de blocos try...catch como mecanismo para o tratamento de erros

b- Se uma informação útil puder ser adicionada ao tratamento de exceção

Crie e lance uma nova exceção com a informação anexa

c- Se a liberação de recursos é requerida

Realize esta liberação de recursos no bloco finally

d- Se erros potenciais não podem ser recuperados na rotina

A recuperação deverá ser tratada pela rotina chamadora e sua estrutura de tratamento de erros

O esquema básico fica retratado pelo seguinte código:

Private Sub Rotina( )
...

Try
 
 'Código a ser executado pela rotina
Catch exc As Exception
  
 'Tratamento de erros
Finally
  
 'Liberação de recursos
End Try

End Sub

private void Rotina( )
{
try
{
// Código da rotina
}
catch (Exception exc)
{
// Tratamento de erros
}
finally
{
// Liberação de recursos
}
}
VB .NET C#
  1. O bloco Try/try contém o código que implementa o método/rotina
  2. O bloco Catch/catch, que é opcional, inclui o código que trata erros específicos mais prováveis de ocorrer e recuperar
  3. O bloco Finally/finally, que é opcional, realiza a liberação requerida. Isso inclui o fechamento de conexões de banco de dados usadas, liberação de objetos criados pelo método, etc. O código deste bloco sempre será executado.

Tabela com orientação para definição do bloco Try... Catch...Finally

Podem ocorrer erros ? Os erros são recuperáveis ? Uma informação de contexto
pode ser adicionada
É exigida liberação ? Combinação Recomendada
Não - x - - x - Não  Nenhuma
Não - x - - x - Sim Try e Finally
Sim Não Não Não  Nenhuma
Sim Não Não Sim Try e Finally
Sim Não Sim Não Try e Catch
Sim Não Sim Sim  Try, Catch e Finally
Sim Sim - x - - x -  Try e Catch

Lembre-se que o .NET Framework não fecha conexões, arquivos, etc. quando ocorre um erro. isso é responsabilidade do programador e deve ser feita no bloco finally, este bloco é a última oportunidade para realizar qualquer liberação antes da infraestrutura de tratamentos de exceção tomar conta da aplicação.

Para ajudar a sua implementação da sua rotina de tratamento de erros temos a seguir um questionário onde com base em suas respostas você pode determinar qual parte do bloco try...catch...finally você irá precisar implementar.

1- Pode ocorrer algum erro nesta rotina ?

R: Se não, então nenhum código para tratamento de erros é requerido.

2- Os erros potenciais são recuperáveis na rotina ?

R: Se ocorreu um erro, mas nada de útil pode ser feito na rotina, a exceção deve ser propagada para a rotina de chamada. Não serve a nenhum propósito útil capturar a exceção e relançá-la.
Esta questão é diferente de :
"São os erros potenciais recuperáveis a nível de aplicativo ?"
Por exemplo, se a rotina tenta gravar um registro em um banco de dados e encontra o registro bloqueado, uma nova tentativa pode ser feita na rotina. No entanto, se um valor é passado para a rotina e as operações resultam em um outro erro, a recuperação não pode ser realizada na rotina, mas deve ser manuseado pela rotina de chamada e a sua estrutura de manipulação de erros

3- Uma informação útil pode ser adicionada à exceção ?

R: As exceções que ocorrem no .NET Framework contém informações detalhadas sobre o erro. No entanto, as exceções não fornecem qualquer informação de contexto sobre o que estava sendo tentado no nível do aplicativo que pode ajudar a solucionar o erro ou fornecer informações mais úteis para o usuário.

Uma nova exceção pode ser criada e lançada com as informações adicionadas. O primeiro parâmetro para o objeto da nova exceção deve conter a mensagem de contexto útil, e o segundo parâmetro deve ser a exceção original. Os mecanismos de tratamento de exceção no .NET Framework criam uma lista ligada de objetos de exceção para criar uma trilha a partir da raiz da exceção até o nível onde a exceção é tratada. Ao passar a exceção original como o segundo parâmetro, a lista encadeada da exceção de raiz é mantida. Exemplo:

Catch exc As Exception
     Throw New Exception("Mensagem de contexto", exc)  
VB .NET
catch (Exception exc)
{
    throw (new Exception("Mensagem de contexto", exc));
}
C#

Para encerrar temos a seguir um código que mostra a utilização de bloco try/catch no interior de laço while para fornecer um mecanismo de tratamento de exceção onde definimos um número de tentativas para que a rotina seja executada novamente:

using System;
using System.Configuration;
using System.Data;
using System.Data.OleDb;

private void atualizaDados(int problemID,String sectionHeading)
{
const int NUM_MAX_TENTATIVAS = 5;

OleDbConnection dbConn = null;
OleDbCommand dCmd = null;
String strConnection = null;
String cmdText = null;
bool updateOK;
int retryCount;

try
{

 // obtem a string de conexão do arquivo web.config e abre a conexão
                strConnection = ConfigurationManager.ConnectionStrings["dbConnectionString"].ConnectionString;
 dbConn = new OleDbConnection(strConnection);
 dbConn.Open( );

 // constroi a instrução SQL para atualizar o registro no banco de dados
 cmdText = "UPDATE Teste " +
                            "SET nome='" + _nome + "' " +
                "WHERE codigo=" + codigoID.ToString( );
dCmd = new OleDbCommand(cmdText, dbConn);

         // fornece um laço com um bloco try catch para facilitar a tentativa de atualização
atualizacaoOK = false;
tentativas = 0;
while ((!atualizacaoOK) &  (tentativas < NUM_MAX_TENTATIVAS))
{

     try
     {
        dCmd.ExecuteNonQuery( );
         atualizacaoOK = true;
     }
     catch (Exception exc)
     {
        tentativas++;
        if (tentativas >= NUM_MAX_TENTATIVAS)
        {
               //lança um anova exceção com a mensagem de contexto informando que o número de
              // tentativas foi execida
                throw new Exception("Máximo de tentativas excedida",exc);
                 }
                            }  

            }//bloco while
}
finally
{
// libera recursos
if (dbConn != null)
{
dbConn.Close( );
}
                        }

}

No código acima observe que temos um bloco try...finally que trata o código para abertura da conexão e atualização da tabela no bloco try e libera os recursos no bloco finally.

Os mecanismos de tratamento de exceções no .NET Framework são poderosos. Além do escopo que abordamos neste artigo, outros tipos de exceções específicas podem ser capturadas e processadas de forma diferente. Além disso, você pode criar novas classes de exceção herdando as classes de exceção base e adicionando a funcionalidade exigida por seus aplicativos.

Rom 8:14 Pois todos os que são guiados pelo Espírito de Deus, esses são filhos de Deus.
Rom 8:15
Porque não recebestes o espírito de escravidão, para outra vez estardes com temor, mas recebestes o espírito de adoção, pelo qual clamamos: Aba, Pai!

Referências: