none
Como melhorar estrutura try?

    Pergunta

  • Olá a todos!

    Desenvolvi uma página de cadastro de clientes com duas ações: o formulário é enviado por e-mail e inserido no banco. Declarei as variáveis, montei a estrutura para envio e inserção, tudo está funcionando perfeitamente. A questão é que gostaria de redirecionar o usuário a uma página de sucesso ou para uma página de erro, dependendo do resultado. Montei uma estrutura assim:

    Code Snippet

                try
                {
                    client.Send(msg);
                    sqlInsertRevenda.Insert();
                    Server.Transfer("~/CadResults.aspx?ok");
                }
                catch (Exception)
                {
                    Server.Transfer("~/CadResults.aspx?erro");
                }



    O problema que está acontecendo é o seguinte: quando a operação é concluída com sucesso e o usuário é redirecionado para a página de sucesso, a página de erro é exibida EMBAIXO da página de sucesso. Só para constar, nas páginas de erro e sucesso eu incluí um timer em javascript de redirecionamento automático para a página inicial.

    Alguém poderia me dar uma luz?

    Muito obrigado a todos. Um abraço!
    João Cunha
    quinta-feira, 24 de abril de 2008 12:58

Respostas

  • A foto só vou conseguir ver depois das 18.. eu só tenho acesso a sites do dominio Microsoft

    Server.Transfer("~/CadResults.aspx?erro");

     

    tenta alterar as duas chamas por:

     

    e se tiver que vc passe por FORM.. ai teria que passar por sessão.. mais veja se isso te ajuda

    Response.Redirect("CadResults.aspx?erro", False)

     

     

    []s

    quinta-feira, 24 de abril de 2008 18:50

  • A resposta é simples. Toda vez que um Response.Redirect() ou Server.Transfer() estiverem num bloco try, o catch (se existir, claro) será executado. Pq? Porque ambos os métodos levantam uma linda System.Threading.ThreadAbortException dizendo: "Thread was being aborted".

    E qual a diferença entre os dois? O Response.Redirect() envia uma resposta para o browser com um header indicando a nova URL para a qual uma nova requisição deve ser feita. Depois deste ponto nada que o teu catch faça vai afetar a resposta para o cliente.

    Já com o Server.Transfer()... não são criadas novas requisições, ao invés disso o servidor acessa os recursos necessários (localmente) e devolve o response. Então ele envia a resposta que é composta pela chamada no bloco try e a do bloco catch ao browser.

    []s


    quinta-feira, 24 de abril de 2008 22:15

Todas as Respostas

  • Joao se ele está entrando no catch é pq esta ocorrendo algum erro... ou o problema pode estar na página CadResults.aspx

     

    faz um teste chamando essa mesma página fora do try passando o mesmo parametro

    quinta-feira, 24 de abril de 2008 13:16
  • o mais indicado seria um tratamento global dos erros da sua aplicação...

    veja em http://www.devaspnet.com.br/colunas/coluna2204.aspx


    quinta-feira, 24 de abril de 2008 13:28
  • Jonax


    Quando elimino o Try, ele executa o server.transfer() corretamente, sem mostrar as duas páginas ao mesmo tempo. O estranho é que com o try não está ocorrendo uma exceção, de fato - o banco é preenchido e o e-mail é enviado corretamente.

    O código que estou usando no pageload da  página CadResults.aspx é o seguinte:

    Code Snippet

    ClientScript.RegisterStartupScript(ClientScript.GetType(), "onLoad", "timer=setTimeout('move()',3000)", true);
            string qs = Request.QueryString.ToString();

            switch (qs)
            {
                case "ok":
                    lblMsg.Text = "Cadastro efetuado com sucesso!";
                    imgOk.Visible = true;
                    break;
                case "erro":
                    lblMsg.Text = "Falha no cadastramento. Por favor, tente novamente mais tarde.";
                    imgErro.Visible = true;
                    break;
            }


    Sandro
    Não resolve minha dúvida, mas você respondeu a uma pergunta que eventualmente eu faria aqui no forum. Obrigado pelo artigo!

    quinta-feira, 24 de abril de 2008 14:06
  • Já tentei diversas modificações na estrutura e o transfer 'duplicado' continua ocorrendo. Alguma sugestão?
    quinta-feira, 24 de abril de 2008 18:01
  • Tenta assim..

     

     

    Server.Transfer("URL", false);

    que eu acho que não dara mais o erro..

     

    Veja se te ajuda

    []s

     

     

    quinta-feira, 24 de abril de 2008 18:18
  • Infelizmente não, Ricardo. Segue um printscreen de um cadastramento bem sucedido para que entendam o problema:

    http://i26.photobucket.com/albums/c113/jaumcunha/error.png
    quinta-feira, 24 de abril de 2008 18:29
  • A foto só vou conseguir ver depois das 18.. eu só tenho acesso a sites do dominio Microsoft

    Server.Transfer("~/CadResults.aspx?erro");

     

    tenta alterar as duas chamas por:

     

    e se tiver que vc passe por FORM.. ai teria que passar por sessão.. mais veja se isso te ajuda

    Response.Redirect("CadResults.aspx?erro", False)

     

     

    []s

    quinta-feira, 24 de abril de 2008 18:50
  • Desculpe, não entendi sua mensagem, acho que veio cortada.
    quinta-feira, 24 de abril de 2008 19:40
  • O Response.Redirect() funciona legal, mas estou curioso sobre por que o Server.Transfer() buga...

    Obrigado!
    quinta-feira, 24 de abril de 2008 19:44

  • A resposta é simples. Toda vez que um Response.Redirect() ou Server.Transfer() estiverem num bloco try, o catch (se existir, claro) será executado. Pq? Porque ambos os métodos levantam uma linda System.Threading.ThreadAbortException dizendo: "Thread was being aborted".

    E qual a diferença entre os dois? O Response.Redirect() envia uma resposta para o browser com um header indicando a nova URL para a qual uma nova requisição deve ser feita. Depois deste ponto nada que o teu catch faça vai afetar a resposta para o cliente.

    Já com o Server.Transfer()... não são criadas novas requisições, ao invés disso o servidor acessa os recursos necessários (localmente) e devolve o response. Então ele envia a resposta que é composta pela chamada no bloco try e a do bloco catch ao browser.

    []s


    quinta-feira, 24 de abril de 2008 22:15
  • Excelente explicação, Laércio! Ajudou bastante...

    Agora uma dúvida: já resolvi o problema da página duplicada usando o Responde.Redirect(), mas você acha que a estrutura do Try está correta? Minha intenção é que as duas ações ocorram ao mesmo tempo - se ocorrer alguma falha no e-mail, o usuário não é cadastrado no banco (e vice-versa).

    Está correto da forma que eu fiz?

    Obrigado mais uma vez, um abraço a todos.
    sexta-feira, 25 de abril de 2008 12:21
  • Use uma transação para controlar a inclusão do usuário. Em casos de erro no envio de e-mail (que deve ser executado após a inclusão) desfaça a inclusão do usuário (rollback).

    []s
    sábado, 26 de abril de 2008 21:58
  • Obrigado pela dica, Laércio! Poderia me dar ou indicar algum exemplo de como fazer isso?

    Muito obrigado!
    segunda-feira, 28 de abril de 2008 12:21

  • Exemplo SIMPLES...

    void InserirUsuario(Usuario usuario) {

    //Inicia a transação

    IniciarTransacao();

    try {

    //Insere seu usuário

    UsuarioRepositorio.Adicionar(usuario);
    //Envia o e-mail
    new EmailServico().Enviar(...;
    // Finaliza a transação
    PersistirTransacao();

    } catch (Exception excecaoQualquer) {

    //Aborta a transação cancelando o insert do usuário

    AbortarTransacao();

    throw new AplicacaoException(excecaoEmail);

    }

    }



    Exemplo,... agora vc pode adequá-lo ao seu contexto.

    []s
    terça-feira, 29 de abril de 2008 14:41