none
Problemas em compatibilidade com BasicHttpBinding RRS feed

  • Pergunta

  •  Olá pessoal, tudo bem?

     Estou com o seguinte problema:  Eu tinha um servidor WebService que minhas aplicações mobiles acessavam ele, agora que estou tentando converter meu servidor pra WCF, esta acontecendo o seguinte problema quando as aplicações tenta invocar qualquer método:

    Falha na solicitação com status HTTP 415: Cannot process the message because the content type 'application/soap+xml; charset=utf-8; action="http://tempuri.org/IWCFCompuService/GetFormPag"' was not the expected type 'text/xml; charset=utf-8'..

     

    aproveitando o post, quero perguntar também se consigo ultilizar o tipo "WSHttpbinding" mesmo com a framework sendo 2.0, por que eu tentei mas a aplicação tenta conectar por 1 min e nada. O código do meu server está aí em baixo:

     

              Mexbinding = new System.ServiceModel.Channels.TcpTransportBindingElement();
              System.ServiceModel.Channels.CustomBinding customBinding = new System.ServiceModel.Channels.CustomBinding(Mexbinding);
    
              AsyncCallback callback = new AsyncCallback(SyncOpen);
              IAsyncResult result = null;
              hostPrincipal = new ServiceHost(principal.GetType());
              tcpBinding = new NetTcpBinding(SecurityMode.Message, true);
              tcpBinding.TransactionFlow = true;
              tcpBinding.MaxBufferSize = int.MaxValue;
              tcpBinding.MaxBufferPoolSize = int.MaxValue;
              tcpBinding.MaxReceivedMessageSize = int.MaxValue;
    
              basicHttpBinding = new BasicHttpBinding(BasicHttpSecurityMode.None);
              basicHttpBinding.MaxBufferPoolSize = int.MaxValue;
              basicHttpBinding.MaxBufferSize = int.MaxValue;
              basicHttpBinding.MaxReceivedMessageSize = int.MaxValue;
              basicHttpBinding.TextEncoding = Encoding.UTF8;
              basicHttpBinding.MessageEncoding = WSMessageEncoding.Text;
    
              /*HttpBinding = new WSHttpBinding(SecurityMode.Message, true);
              HttpBinding.TransactionFlow = true;
              HttpBinding.MaxBufferPoolSize = int.MaxValue;
              HttpBinding.MaxReceivedMessageSize = int.MaxValue;*/
    
              namedPipeBinding = new NetNamedPipeBinding(NetNamedPipeSecurityMode.Transport);
              namedPipeBinding.MaxBufferPoolSize = int.MaxValue;
              namedPipeBinding.MaxBufferSize = int.MaxValue;
              namedPipeBinding.MaxReceivedMessageSize = int.MaxValue;
              namedPipeBinding.TransactionFlow = true;
    
              hostPrincipal.AddServiceEndpoint(typeof(CompuService.IWCFCompuService), tcpBinding, uriNetTcp);
              hostPrincipal.AddServiceEndpoint(typeof(CompuService.IWCFCompuService), basicHttpBinding, uriWSHttp);
              hostPrincipal.AddServiceEndpoint(typeof(CompuService.IWCFCompuService), namedPipeBinding, uriNetPipe);
              
              metaData = hostPrincipal.Description.Behaviors.Find<ServiceMetadataBehavior>();
              if (metaData == null)
              {
                metaData = new ServiceMetadataBehavior();
                metaData.HttpGetUrl = new Uri("http://localhost:90/CompuService");
                metaData.HttpGetEnabled = true;
                //metaData.HttpGetBinding = basicHttpBinding;
                hostPrincipal.Description.Behaviors.Add(metaData);
              }
              hostPrincipal.AddServiceEndpoint(typeof(IMetadataExchange), customBinding, uriNetTcpMex);
    
              hostPrincipal.Closing += new EventHandler(Host_Closing);
    
              result = hostPrincipal.BeginOpen(callback, principal);
              hostPrincipal.EndOpen(result);
    

    desde já agradeço

    quarta-feira, 1 de setembro de 2010 14:46

Respostas

  • Boas Pedro,

    Para você ter uma ideia do que fiz aqui para reproduzir:

    Crei uma aplicação ASP.NET Web Services (ASMX) com um único serviço, que está abaixo:

    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]
    public class Service1 : System.Web.Services.WebService
    {
        [WebMethod]
        public DataSet HelloWorld()
        {
            DataSet ds = new DataSet();
            DataTable dt = new DataTable();

            dt.Columns.Add("Nome");
            dt.Rows.Add("Israel");

            ds.Tables.Add(dt);
            return ds;
        }
    }

    Depois disso, rodei o serviço e ele foi publicado no seguinte endereço: http://localhost:51982/Service1.asmx. Com isso, fiz a referência para o mesmo em uma aplicação Windows para assim consumir. Depois da referência feita (utilizando a opção antiga, que é para referenciar serviços ASMX), eu escrevi o seguinte código para consumo:

    Service1 s = new Service1();
    DataSet ds = s.HelloWorld();
    Console.WriteLine(ds.Tables[0].Rows[0][0]);

    E agora tenho o serviço publicado em ASMX e o consumo utilizando a parte cliente desta mesma tecnologia. Agora decidi mudar o lado do servidor para WCF. Para isso, eu criei a seguinte estrutura:

    class Program
    {
        static void Main(string[] args)
        {
            using (ServiceHost host = new ServiceHost(typeof(Servico), new Uri[] { }))
            {
                host.AddServiceEndpoint(typeof(IContrato), new BasicHttpBinding(), "http://localhost:51982/Service1.asmx");
                host.Open();

                Console.WriteLine("rodando..");
                Console.ReadLine();
            }
        }
    }

    [ServiceContract]
    interface IContrato
    {
        [OperationContract]
        DataSet HelloWorld();
    }

    public class Servico : IContrato
    {
        public DataSet HelloWorld()
        {
            DataSet ds = new DataSet();
            DataTable dt = new DataTable();

            dt.Columns.Add("Nome");
            dt.Rows.Add("Israel");

            ds.Tables.Add(dt);
            return ds;
        }
    }

    Só que quando rodei desta forma, obtive o seguinte problema:

    Unhandled Exception: System.Web.Services.Protocols.SoapHeaderException: The mess
    age with Action 'http://tempuri.org/HelloWorld' cannot be processed at the recei
    ver, due to a ContractFilter mismatch at the EndpointDispatcher. This may be bec
    ause of either a contract mismatch (mismatched Actions between sender and receiv
    er) or a binding/security mismatch between the sender and the receiver.  Check t
    hat sender and receiver have the same contract and the same binding (including s
    ecurity requirements, e.g. Message, Transport, None).


    Como havia dito, o problema está na SOAPAction, o que me obrigou a mudar um detalhe no contrato, que foi a customização da propriedade Action:

    [ServiceContract]
    interface IContrato
    {
        [OperationContract(Action = "http://tempuri.org/HelloWorld")]
        DataSet HelloWorld();
    }


    http://www.israelaece.com
    quinta-feira, 2 de setembro de 2010 11:23
    Moderador

Todas as Respostas

  • Boas Pedro,

    Como está a configuração do serviço que você está expondo para os clientes?
    http://www.israelaece.com
    quarta-feira, 1 de setembro de 2010 15:03
    Moderador
  •  Olá Israel, tudo bem?

     Bem, toda a configuração é o código acima.

    quarta-feira, 1 de setembro de 2010 15:14
  • Boas Pedro,

    Eu fiz uma simulação aqui, e o problema pode estar sendo a SOAP Action.

    Provavelmente o teu serviço ASMX publicava a action para a operação como algo sendo http://tempuri.org/TuaOperacaoAqui, só que o WCF inclui o nome do contrato, por exemplo: http://tempuri.org/IContrato/TuaOperacaoAqui

    Então, tente definir explicitamente a ação através do atributo OperationContractAttribute, para manter compatibilidade com o ASMX:

    [ServiceContract]
    interface IContrato
    {
        [OperationContract(Action = "http://tempuri.org/TuaOperacaoAqui")]
        string HelloWorld();
    }
    http://www.israelaece.com
    quarta-feira, 1 de setembro de 2010 16:07
    Moderador
  •  Olá Israel, tudo bem?

     

     Mesmo alterando o Action com o parametro Action do atributo ainda está tendo a mensagem, e o engraçado que pela mensagem o contrato ainda está incluso, mesmo na referência não incluindo o contrato. Está abaixo o contrato:

     

            [OperationContract(Action="http://tempuri.org/GetFormPag")]

            System.Data.DataSet GetFormPag(int Codigo);

     

     

    quarta-feira, 1 de setembro de 2010 19:31
  • Boas Pedro,

    Como está a configuração do seu WebService (ASMX)?
    http://www.israelaece.com
    quarta-feira, 1 de setembro de 2010 19:54
    Moderador
  •  O meu WebService só está ultilizando autenticação via usuario e senha:

     

    public class AuthHeader : SoapHeader
    {
      //<returns>string</returns>
      public string UserName;
      //<returns>string</returns>
      public string Password;
    }
    
    [AttributeUsage(AttributeTargets.Method)]
    public class AuthExtensionAttribute : SoapExtensionAttribute
    {
      int _priority = 1;
    
      public override int Priority
      {
        get { return _priority; }
        set { _priority = value; }
      }
    
      public override Type ExtensionType
      {
        get { return typeof(AuthExtension); }
      }
    }
    
    public class AuthExtension : SoapExtension
    {
      public override void ProcessMessage(SoapMessage message)
      {
        if (message.Stage == SoapMessageStage.AfterDeserialize)
        {
          string UserName = string.Empty;
          string UserPass = string.Empty;
          foreach (SoapHeader header in message.Headers)
          {
            if (header is AuthHeader)
            {
              AuthHeader credentials = (AuthHeader)header;
              UserName = credentials.UserName.ToUpper();
              UserPass = credentials.Password.ToUpper();
    
              if (UserName == "COMPUFORTE" &&
                UserPass == "COMPUXPTO")
                return;
    
              break;
            }
          }
    
          throw new SoapException("Você não tem permissão para acessar esta aplicação." + UserName + " - " +UserPass,
            SoapException.ClientFaultCode);
        }
      }
    
      public override Object GetInitializer(Type type)
      {
        return GetType();
      }
    
      public override Object GetInitializer(LogicalMethodInfo info,
        SoapExtensionAttribute attribute)
      {
        return null;
      }
    
      public override void Initialize(Object initializer)
      {
    
      }
    }
    

     aí eu ultilizo nos metodos o AuthExtensionAttribute.

     

      [AuthExtension]
      [SoapHeader("Credentials")]
      [WebMethod(Description = "Faz o Login do Usuário.", EnableSession = true)]
      public UserInformation.User Login(string UserName, string UserPass, string Terminal)
    

    quarta-feira, 1 de setembro de 2010 20:15
  • Boas Pedro,

    E como estão os endereços? Você está substituindo para o WCF e mantendo o mesmo endereço?
    http://www.israelaece.com
    quarta-feira, 1 de setembro de 2010 21:20
    Moderador
  • Boas Pedro,

    Para você ter uma ideia do que fiz aqui para reproduzir:

    Crei uma aplicação ASP.NET Web Services (ASMX) com um único serviço, que está abaixo:

    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]
    public class Service1 : System.Web.Services.WebService
    {
        [WebMethod]
        public DataSet HelloWorld()
        {
            DataSet ds = new DataSet();
            DataTable dt = new DataTable();

            dt.Columns.Add("Nome");
            dt.Rows.Add("Israel");

            ds.Tables.Add(dt);
            return ds;
        }
    }

    Depois disso, rodei o serviço e ele foi publicado no seguinte endereço: http://localhost:51982/Service1.asmx. Com isso, fiz a referência para o mesmo em uma aplicação Windows para assim consumir. Depois da referência feita (utilizando a opção antiga, que é para referenciar serviços ASMX), eu escrevi o seguinte código para consumo:

    Service1 s = new Service1();
    DataSet ds = s.HelloWorld();
    Console.WriteLine(ds.Tables[0].Rows[0][0]);

    E agora tenho o serviço publicado em ASMX e o consumo utilizando a parte cliente desta mesma tecnologia. Agora decidi mudar o lado do servidor para WCF. Para isso, eu criei a seguinte estrutura:

    class Program
    {
        static void Main(string[] args)
        {
            using (ServiceHost host = new ServiceHost(typeof(Servico), new Uri[] { }))
            {
                host.AddServiceEndpoint(typeof(IContrato), new BasicHttpBinding(), "http://localhost:51982/Service1.asmx");
                host.Open();

                Console.WriteLine("rodando..");
                Console.ReadLine();
            }
        }
    }

    [ServiceContract]
    interface IContrato
    {
        [OperationContract]
        DataSet HelloWorld();
    }

    public class Servico : IContrato
    {
        public DataSet HelloWorld()
        {
            DataSet ds = new DataSet();
            DataTable dt = new DataTable();

            dt.Columns.Add("Nome");
            dt.Rows.Add("Israel");

            ds.Tables.Add(dt);
            return ds;
        }
    }

    Só que quando rodei desta forma, obtive o seguinte problema:

    Unhandled Exception: System.Web.Services.Protocols.SoapHeaderException: The mess
    age with Action 'http://tempuri.org/HelloWorld' cannot be processed at the recei
    ver, due to a ContractFilter mismatch at the EndpointDispatcher. This may be bec
    ause of either a contract mismatch (mismatched Actions between sender and receiv
    er) or a binding/security mismatch between the sender and the receiver.  Check t
    hat sender and receiver have the same contract and the same binding (including s
    ecurity requirements, e.g. Message, Transport, None).


    Como havia dito, o problema está na SOAPAction, o que me obrigou a mudar um detalhe no contrato, que foi a customização da propriedade Action:

    [ServiceContract]
    interface IContrato
    {
        [OperationContract(Action = "http://tempuri.org/HelloWorld")]
        DataSet HelloWorld();
    }


    http://www.israelaece.com
    quinta-feira, 2 de setembro de 2010 11:22
    Moderador
  • Boas Pedro,

    Para você ter uma ideia do que fiz aqui para reproduzir:

    Crei uma aplicação ASP.NET Web Services (ASMX) com um único serviço, que está abaixo:

    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]
    public class Service1 : System.Web.Services.WebService
    {
        [WebMethod]
        public DataSet HelloWorld()
        {
            DataSet ds = new DataSet();
            DataTable dt = new DataTable();

            dt.Columns.Add("Nome");
            dt.Rows.Add("Israel");

            ds.Tables.Add(dt);
            return ds;
        }
    }

    Depois disso, rodei o serviço e ele foi publicado no seguinte endereço: http://localhost:51982/Service1.asmx. Com isso, fiz a referência para o mesmo em uma aplicação Windows para assim consumir. Depois da referência feita (utilizando a opção antiga, que é para referenciar serviços ASMX), eu escrevi o seguinte código para consumo:

    Service1 s = new Service1();
    DataSet ds = s.HelloWorld();
    Console.WriteLine(ds.Tables[0].Rows[0][0]);

    E agora tenho o serviço publicado em ASMX e o consumo utilizando a parte cliente desta mesma tecnologia. Agora decidi mudar o lado do servidor para WCF. Para isso, eu criei a seguinte estrutura:

    class Program
    {
        static void Main(string[] args)
        {
            using (ServiceHost host = new ServiceHost(typeof(Servico), new Uri[] { }))
            {
                host.AddServiceEndpoint(typeof(IContrato), new BasicHttpBinding(), "http://localhost:51982/Service1.asmx");
                host.Open();

                Console.WriteLine("rodando..");
                Console.ReadLine();
            }
        }
    }

    [ServiceContract]
    interface IContrato
    {
        [OperationContract]
        DataSet HelloWorld();
    }

    public class Servico : IContrato
    {
        public DataSet HelloWorld()
        {
            DataSet ds = new DataSet();
            DataTable dt = new DataTable();

            dt.Columns.Add("Nome");
            dt.Rows.Add("Israel");

            ds.Tables.Add(dt);
            return ds;
        }
    }

    Só que quando rodei desta forma, obtive o seguinte problema:

    Unhandled Exception: System.Web.Services.Protocols.SoapHeaderException: The mess
    age with Action 'http://tempuri.org/HelloWorld' cannot be processed at the recei
    ver, due to a ContractFilter mismatch at the EndpointDispatcher. This may be bec
    ause of either a contract mismatch (mismatched Actions between sender and receiv
    er) or a binding/security mismatch between the sender and the receiver.  Check t
    hat sender and receiver have the same contract and the same binding (including s
    ecurity requirements, e.g. Message, Transport, None).


    Como havia dito, o problema está na SOAPAction, o que me obrigou a mudar um detalhe no contrato, que foi a customização da propriedade Action:

    [ServiceContract]
    interface IContrato
    {
        [OperationContract(Action = "http://tempuri.org/HelloWorld")]
        DataSet HelloWorld();
    }


    http://www.israelaece.com
    quinta-feira, 2 de setembro de 2010 11:23
    Moderador