none
Erro The creator of this fault did not specify a Reason e propagação do erro no serviço para o cliente RRS feed

  • Pergunta

  • Amigos,

    Construi uma pequena aplicação e desenvolvi o serviço desta forma:

    Classe que armazena o detalhe do erro que será passada para o cliente através de uma faultexception:

    using

     

     

    System;

    namespace

     

     

    Jetro.WCF

    {

     

     

    public class DetalhesDoErro

    {

     

     

    public string Mensagem { get; set; }

    }

    }

    Aqui está a interface do serviço:

    [

     

    OperationContract]

    [

     

    FaultContract(typeof(DetalhesDoErro))]

     

     

    bool UsuarioNaoCadastrado(string Nome);

    Aqui está a implementação do serviço:

     

     

    public bool UsuarioNaoCadastrado(string Nome)

    {

     

     

    try

    {

     

     

    using (var BLL = new UsuarioBLL())

    {

     

     

    var conexaoBanco = WebConfigurationManager.ConnectionStrings["ConexaoBanco"].ConnectionString;

     

     

    return BLL.UsuarioNaoCadastrado(Nome, conexaoBanco);

    }

    }

     

     

    catch (Exception ex)

    {

     

     

    DetalhesDoErro detalhesErro = new DetalhesDoErro();

    detalhesErro.Mensagem = ex.Message;

     

     

    throw new FaultException<DetalhesDoErro>(detalhesErro);

    }

    }

    Aqui está como eu faço no cliente para pegar o erro:

     

     

    JetroClient Proxy = new JetroClient();

     

     

    using (Proxy as IDisposable)

    {

     

     

    try

    {

    Proxy.UsuarioNaoCadastradoAsync(cmbUsuarios.Text);

    Proxy.UsuarioNaoCadastradoCompleted +=

     

    new EventHandler<UsuarioNaoCadastradoCompletedEventArgs>(Proxy_UsuarioNaoCadastradoCompleted);

    }

     

     

    catch (FaultException<JetroWCF.DetalhesDoErro> ex)

    {

     

     

    MessageBox.Show(ex.Detail.Mensagem);

    }

    }

    Está acontecendo dois problemas que são:

    1) No lado do serviço está acontecendo este erro: The creator of this fault did not specify a Reason, nesta linha:throw new FaultException<DetalhesDoErro>(detalhesErro).Se eu altero ela para que fique assim:throw new FaultException<DetalhesDoErro>(detalhesErro, new FaultReason(detalhesErro.Mensagem)) funciona e passa. A minha dúvida é se esta construção está certa e tem que ser feita dessa forma, ou seja, especificando a FaultReason?

    2) O segundo problema é que eu não estou conseguindo exibir a mensagem do erro que aconteceu no serviço no lado do cliente. Sempre é exibida a mensagem:The remote server returned an error: NotFound, e ai aparece um montão de palavrões...rs

    Por favor, seria possível alguém dar uma luz?

    Um forte abraço a todos.

    terça-feira, 4 de janeiro de 2011 13:23

Respostas

Todas as Respostas

  • Boas Marcelo,

    A questão é que você está invocando a operação de forma assíncrona, ou seja, se algum problema ocorrer durante a execução da mesma, a exceção vai ser reportada dentro do evento que acontece quando a chamada é finalizada, que no seu caso é a Proxy_UsuarioNaoCadastradoCompleted. É dentro deste evento que deve estar o tratamento de erro.
    http://www.israelaece.com
    terça-feira, 4 de janeiro de 2011 15:19
    Moderador
  • Bom dia Marcelo.

     

    Em relação ao seu primeiro problema, isto acontece porque uma FaultException, ao ser lançada requer que uma FaultReason seja especificada na propriedade Reason.

    Quando você passa a mensagem como parametro ao construtor, ele automaticamente cria a FaultReason. Portanto você pode criar a FaultException passando a string que representa a FaultReason ou pode criar o objeto e depois atribuir a FaultReason.

    Já em relação ao segundo problema, faultou você definir a sua classe DetalhesDoErro como um contrato de dados, colocando a annotation DataContract na classe e DataMember nos atributos. Como você já colocou a annotation FaultContract nos métodos, tudo deve funcionar. E assim como falado acima, você deve invocar o método de forma síncrona.

    Seguem alguns links que explicam melhor o que eu disse.



    Espero ter ajudado. Qualquer dúvida estou à disposição.
    terça-feira, 4 de janeiro de 2011 15:37
  • Marcelo,

    Se você estiver debugando podem ser as configurações do Visual Studio. Vá em Tools -> Options -> Debugging -> General.

    As opções "Enable the exception assistant" e "Enable just my Code (Managed only)" devem ser desmarcadas.

    Espero ter ajudado.

    Allan Ferreira


    Allan
    terça-feira, 4 de janeiro de 2011 21:07
  • Amigos,

    Obrigado pelas respostas rápidas de todos vocês.

    Porém ainda estou com dúvidas de como resolver este problema, e por alguma razão que eu não sei, eu ainda não estou conseguindo pegar a mensagem de erro que acontece no servico e mostrar no cliente.

    Estou usando WCF, SL4, C# em uma aplicação n-camadas, então de acordo com todas as respostas eu fiz as seguintes alterações:

    • Classe de irá transportar o erro do serviço para o cliente: Eu acrescentei as propriedade DataContract e DataMember e ela ficou dessa forma:

      namespace

       

       

      Jetro.WCF
      {
        [
      DataContract]
        public class DetalhesDoErro
        {
          [
      DataMember]
         
      public string Mensagem { get; set; }
        }
      }

    • Camada DAL: Nesta camada eu tenho um método que verifica se o usuário está cadastrado pelo nome, e para testar a geração do erro e pega-lo no cliente, de propósito eu escrevi o nome do campo errado na declaração SQL.

      O método ficou assim:

      public

       

       

      bool UsuarioNaoCadastrado(string Nome, string ConexaoBanco)
      {
       
      using (var conexaoBanco = new SqlConnection(ConexaoBanco))
        {
         
      using (var cmdSql = new SqlCommand())
          {
            cmdSql.Connection = conexaoBanco;
            cmdSql.CommandText =
      "Select NomeUsuario from Usuario " +
           
      //"Where Upper(NomeUsuario) = '" + Nome.ToUpper() + "'"; **Linha correta
            "Where Upper(NomeUsu) = '" + Nome.ToUpper() + "'"; **Linha Errada

            cmdSql.Connection.Open();
           
      using (var dr = cmdSql.ExecuteReader())
            {
             
      if (dr.HasRows == false)
               
      return true;
             
      else
               
      return false;
             }
           }
         }
        }

    • Camada BLL: A chamda do método nesta camada ficou dessa forma:

      public

       

       

      bool UsuarioNaoCadastrado(string Nome, string ConexaoBanco)
      {
       
      using (var DAL = new UsuarioDAL())
        {
         
      return DAL.UsuarioNaoCadastrado(Nome, ConexaoBanco);
        }
      }

    • Serviço : Na implementação do serviço fiz desta forma:

      public

       

       

      bool UsuarioNaoCadastrado(string Nome)
      {
       
      try
       
      {
         
      using (var BLL = new UsuarioBLL())
          {
           
      var conexaoBanco = WebConfigurationManager.ConnectionStrings["ConexaoBanco"].ConnectionString;
           
      return BLL.UsuarioNaoCadastrado(Nome, conexaoBanco);
           }
        }
        
      catch (Exception ex)
        {
         
      DetalhesDoErro detalhesErro = new DetalhesDoErro();
          detalhesErro.Mensagem = ex.Message;
         
      throw new FaultException<DetalhesDoErro>(detalhesErro, new FaultReason(detalhesErro.Mensagem));
        }
      }

    • Página do Silverlight: Testou fazendo desta forma a chamada ao serviço:

       

       

      JetroClient Proxy = new JetroClient();
      using (Proxy as IDisposable)
      {
        Proxy.UsuarioNaoCadastradoAsync(cmbUsuarios.Text);
        Proxy.UsuarioNaoCadastradoCompleted +=
      new
         
      EventHandler<UsuarioNaoCadastradoCompletedEventArgs>   (Proxy_UsuarioNaoCadastradoCompleted);
      }

    • Evento UsuarioNaoCadastradoCompleted: Eu tento pegar o erro desta forma:

       

       

      void Proxy_UsuarioNaoCadastradoCompleted(object sender, UsuarioNaoCadastradoCompletedEventArgs e)
      {
       
      if (e.Error == null)
        {

        }
       
      else if (e.Error is FaultException<DetalhesDoErro>)
        {
         
      FaultException<DetalhesDoErro> erro = e.Error as FaultException<DetalhesDoErro>;
         
      MessageBox.Show(erro.Detail.Mensagem);
        }
      }

      Ao debugar vejo que o erro que é retornado para o cliente é o System.ServiceModel,CommunicationExcpetion, e não o FaultException que fiz no serviço.

      E eu realmente não entendi porque isso acontece, já que no serviço eu tranformo tudo em FaultException, independente do tipo do erro, ou não é assim?

      Desculpe pela dissertação acima e obrigado a todos que puderem ajudar

     

     


    quarta-feira, 5 de janeiro de 2011 12:41
  • Boas Marcelos,

    Coloca isso na sua aplicação Silverlight:

    WebRequest.RegisterPrefix("http://", WebRequestCreator.ClientHttp);

    Mais informações:

    http://www.israelaece.com/post/Stacks-de-Comunicacao-do-Silverlight.aspx
    http://www.israelaece.com/post/Propagando-excecoes-para-o-Silverlight.aspx


    http://www.israelaece.com
    quarta-feira, 5 de janeiro de 2011 14:10
    Moderador
  • Grande Israel!

    Cara FUNCIONOU após colocar essa declaração!!!!

    Sem palavras para agrace-lo, simplesmente fantástico!

    Um forte abraço.

     

    quarta-feira, 5 de janeiro de 2011 14:55