none
Exibir ao cliente a mensagem de uma Exception RRS feed

  • Pergunta

  • Olá,

    Fiz esta pergunta no forum "Silverlight", mas acho que postei no local errado (hehehehe).

    Alguem tem uma ideia de como exibir ao cliente (Silverlight) a mensagem de uma Exception que foi gerada numa camada antes do WCF ?

    Ex:
    -Camadas (Biz, Crud, Provider, etc..) -->> "aqui gera a exception"
    -WebService (WCF)
    -Cliente (Tela de Manutenção dos Dados) -->> "aqui quero exibir a mensagem"

    abs,

    Pedro Palma
    quarta-feira, 13 de maio de 2009 13:56

Respostas

Todas as Respostas

  • Boas Pedro,

    O WCF possui várias técnicas para propagar as exceções geradas. Essas técnicas você pode ver neste artigo: http://www.israelaece.com/post/WCF-Error-Handling.aspx.

    Somente tome cuidado para gerar a exceção, para não expor mais detalhes da sua implementação interna para os clientes. Além disso, em tempo de desenvolvimento não "coma" as exceções, limpando a stack trace, pois você nunca saberá o que realmente ocorreu.
    http://www.israelaece.com
    quarta-feira, 13 de maio de 2009 15:14
    Moderador
  • Olá Israel,

    Primeiramente muito obrigado por ter respondido prontamente a minha dúvida.
    Eu já havia lido o seu artigo e voltei a ler novamente, que por sinal, todos os seus artigos são excelentes.
    Infelizmente não consegui aplicá-lo no meu projeto.
    Veja bem, eu já tenho a solução rodando em windows e quero aproveitar as camadas (Biz, Crud, Provider, etc) para poder criar uma aplicação Web com a interface Silverlight.
    Para resolver esta situação, então criei uma camada WCF para poder acessar as regras e dados existentes nas outras camadas.
    O que eu preciso é exibir ao usuário o erro ocorrido nas camadas anteriores.

    Exemplo de como esta a aplicação:

    // Camada de Acesso a Dados
    //-----------------------------

    public List<tbClientes> GetClientes()
    {
        List<tbClientes> clientes = new tbClientes();
        try
        {
            //.........
            //.........
            // Aqui ocorre o erro 
            //.........
            //.........
        }
        catch(Exception ex)
        {
            throw new Exception("Erro na leitura tbClientes" + ex.Message);
        }
        return clientes;
    }


    // Camada WCF
    //---------------

    [OperationContract]

    public List<tbClientes> ConsultaClientes()
    {
        return new Crud().GetClientes();
    }


    // Interface do Usurio (Silverlight)
    //---------------------------------

    private void RecuperaDadosDeClientes()
    {
        var proxy = new WcfClientesClient();
        proxy.ConsultaClientesCompleted +=
    new EventHandler<ConsultaClientesCompletedEventArgs>(proxy_ConsultaClientesCompleted);
        proxy.ConsultaClientesAsync();
    }

    private
    void proxy_ConsultaClientesCompleted(object sender, ConsultaClientesCompletedEventArgs e)
    {
        if (e.Result != null)
        {
            grdClientes.ItemsSource = e.Result;
        }
    }

    //---------------------------------------

    Se vc puder me dar uma força, ficarei muito grato

    abs,


    Pedro Palma

    quinta-feira, 14 de maio de 2009 11:33
  • Boas Pedro,

    Bem, o primeiro detalhe é adicionar a exceção que está ocorrendo dentro do seu método GetClientes, como InnerException da Exception que está disparando, algo mais ou menos como:

    catch(Exception ex)
    {
        throw new Exception("Erro na leitura tbClientes.", ex);
    }

    Isso evitará a limpeza da stacktrace, mostrando exatamente onde o problema ocorreu. Também notei que você está utilizando a chamada assíncrona do método. Quando o proxy é gerado com essa versão do método, um evento é também criado para determinar o fim da execução, que no seu caso é ConsultaClientesCompleted. Este evento tem um argumento que herda de AsyncCompletedEventArgs, que por sua vez, disponibiliza uma propriedade chamada Exception. Você pode avaliá-la para ver se ocorreu ou não problema na execução do processo assíncrono, exemplo:

    private void proxy_ConsultaClientesCompleted(object sender, ConsultaClientesCompletedEventArgs e)
    {
        if (e.Exception != null) throw e.Exception;

        if (e.Result != null)
        {
            grdClientes.ItemsSource = e.Result;
        }
    }


    http://www.israelaece.com
    quinta-feira, 14 de maio de 2009 14:11
    Moderador
  • Olá Israel,

    Obrigado pela atenção.
    Estou usando o Framework 3.5 e Silverlight 2.0.
    Não encontrei a propriedade Exception.
    As propriedades apresentadas no intellisense são Cancelled, Error, Result e UserState.
    Testei a propriedade "Error" e consegui detectar a ocorrência do erro, só não consegui pegar o valor da mensagem gerada no metodo GetClientes. Se eu usar a sintaxe "e.Error.Message", será mostrado uma mensagem sem sentido ao usuário: "The remote server returned an erro: NotFound".
    Será que não é possivel pegar o valor exato que foi setado a mensagem ?

    abs,


    Pedro Palma
    quinta-feira, 14 de maio de 2009 15:13
  • Boas Pedro,

    Desculpe-me, a propriedade é Error, o tipo dela que é Exception.

    Você está utilizando o FaultContract, mostrando as possíveis exceções que o teu contrato pode disparar? Caso não, toda exceção é transformada em FaultException. Outro detalhe: está definindo o atributo IncludeExceptionDetailInFaults como true?

    Quando não tem erro, o método executa normalmente?
    http://www.israelaece.com
    quinta-feira, 14 de maio de 2009 15:26
    Moderador
  • Olá Israel,

    Não estou utilizando FaultContract. Tentei usar, mas se eu usar, não consigo instanciar a classe (WCF) no metodo "RecuperaDadosDeClientes" que esta no programa principal. Quando estou escrevendo o nome da classe, a IDE ja alerta para o erro "The type or namespace name "WcfClientesClient" could not be found (are you missing a using directive or an assembly reference)".
    O atributo IncludeExceptionDetailInFaults esta definido como false. Testei tambem como true, mas sem sucesso.
    O método "RecuperaDadosDeClientes" é executado normalmente quando não tem erros.

    abs,
    Pedro Palma
    quinta-feira, 14 de maio de 2009 18:03
  • Boas,

    Já tentou vasculhar a InnerException da exceção para ver se enxerga a exceção interna?

    Não entendi isso: "Tentei usar, mas se eu usar, não consigo instanciar a classe"
    http://www.israelaece.com
    quinta-feira, 14 de maio de 2009 18:05
    Moderador
  • Israel,

    Sobre "Tentei usar ...." :
    Quando eu aplico ao método o atributo FaultContract, não consigo criar um proxy.

    Vasculhando "MessageBox.Show(e.Error.InnerException.ToString())", não aparece referencia alguma a exceção, veja cópia da mensagem

    System.Net.WebException: The remote server returned an error: NotFound --->
    System.Net.WebException: The remote server returned an error: NotFound
      at System.Net.BrowserHttpWebRequest.InternalEndGetResponse(IAsyncResult asyncResult)
      at System.Net.BrowserHttpWebRequest.<>c_DisplayClass5.<EndGetResponse>b_4(Object sendState)
      at System.Net.AsyncHelper.<>c_DisplayClass2.<BeginOnUI>b_0(Object sendState)
      --- End of inner exception stack trace ---
      at System.Net.AsyncHelper.BeginOnUI(SendOrPostCallback beginMethod, Object state)
      at System.Net.BrowserHttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
      at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelAsyncRequest.CompleteGetResponse(IAsyncResult result)

     


    Pedro Palma
    quinta-feira, 14 de maio de 2009 18:50
  • Boas Pedro,

    Estranho, a mensagem da Exception não reflete o que está sendo disparado pelo componente.

    Tem um e-mail para lhe enviar um exemplo?
    http://www.israelaece.com
    sexta-feira, 15 de maio de 2009 02:17
    Moderador
  • Olá Israel,

    Tenho sim, vc pode enviar para pedro@dbcontrol.com.br

    Me desculpa pela insistência, é que já estou pesquisando a alguns dias e não encontrei uma saida plausivel para esta situação.

    obrigado pela ajuda
    sexta-feira, 15 de maio de 2009 11:39
  • Boas Pedro,

    O que me veio a cabeça que talvez seja o seu problema, é a ausencia do arquivo ClientAccessPolicy.xml no teu serviço: http://msdn.microsoft.com/en-us/library/cc838250(VS.95).aspx#crossdomain_communication
    http://www.israelaece.com
    sexta-feira, 15 de maio de 2009 14:00
    Moderador
  • Israel,

    Eu tenho este arquivo na pasta C:\inetpub\wwwrot\GlobalWeb, ou seja, pasta raiz da aplicação.
    O arquivo é o default:

    <?xml version="1.0" encoding="utf-8" ?>
    <access-policy>
      <cross-domain-access>
        <policy>
          <allow-from http-request-headers="*">
            <domain uri="*"/>
          </allow-from>
          <grant-to>
            <resource path="/" include-subpaths="true"/>
          </grant-to>
        </policy>
      </cross-domain-access>
    </access-policy>

    abs,


    Pedro Palma
    sexta-feira, 15 de maio de 2009 15:12
    • Marcado como Resposta Pedro Palma sexta-feira, 15 de maio de 2009 19:49
    sexta-feira, 15 de maio de 2009 17:37
    Moderador
  • Olá Israel,

    Eu havia lido este artigo, só que não havia testado, pois achava que teria uma solução mais genérica sobre a propagação de mensagem.

    Bom, agora efetuei vários testes e todos foram muito bem sucedidos.

    Substitui "catch (FaultException<ArgumentException> ex)" por "catch (Exception ex)"  para não ter que alterar nenhuma das mensagens existentes nas camadas em uso e funcionou muito bem.

    Talvez nas próximas versões do Silverlight este problema seja resolvido, até lá, vou usando esta solução que atende as minhas necessidades.

    Muito obrigado pela atenção dada sobre este assunto e quando nos encontrarmos pagarei as devidas e merecidas cervejas, hehehe

    Por enquanto, Deus te abençoe,

    Abs,

    Pedro Palma
    sexta-feira, 15 de maio de 2009 19:48