Chamada via web service SOAP

Existe uma limitação no tamanho do pacote a ser enviada para nosso web service de integração com o Mega, onde caso o xml a ser enviado tenha um tamanho superior a 1,5Mb, o xml e o processo de envio necessitam ser particionados, e ser enviado uma porção do xml de cada vez.


Funcionamento


Para o envio do xml em partes, o web service deverá se ser chamado uma vez para cada parte e conforme as partes são enviadas elas ficarão salvas em disco no servidor, assim quando a última parte for enviada todas as outras partes já enviadas serão concatenadas formando novamente o xml e assim dando início ao processo de integração.
A primeira chamada deverá ter o parâmetro 'pPrimeiraParte' com o valor 'true' para indicar que é o início do envio, assim como a última parte também deverá ter o parâmetro 'pUltimaParte' com o valor 'true' para indicar o fim do envio. Ainda na primeira chamada o parâmetro pGUID pode ter o seu valor vazio, uma vez que esse parâmetro será utilizado nas próximas chamadas.

Quando a primeira parte do xml chegar no server, será gerado um 'GUID'(Identificador único universal) aleatoriamente, que será o retorno da primeira chamada dentro da tag 'Mensagem' do xml. Esse 'GUID' será utilizado para compor o nome de cada parte do xml salvo em disco, de forma que o nome será formado pelo 'GUID' seguido da ordem da parte, por exemplo, 1 para primeira parte, 2 para a segunda parte e assim por diante. Por isso, a necessidade de se passar no parâmetro 'pGuid'. 
O 'GUID' gerado na primeira chamada e em todas as demais, é o que determina a ligação entre as partes do xml. Para as demais partes, com exceção da última, a chamada deverá ser feita passando os parâmetros 'pPrimeiraParte' e 'pUltimaParte' com valor false. No parâmetro 'pNumeroParte' deverá ser passado o número da parte a ser enviada, e por fim o parâmetro 'pXml' com o valor da parte a ser enviada. A chamada da última parte é igual as demais, com exceção do parâmetro 'pUltimaParte', que deverá ter o valor 'true'. 
Ao chegar no servidor a última parte, será feita uma busca por todos os arquivos que comecem com o 'GUID passado por parâmetro e o conteúdo dos arquivos será concatenado na sequência, para então formar o xml a ser processado pelo Integrador. 


A responsabilidade de verificar o tamanho do xml é da aplicação que consome o serviço.
O tamanho máximo de uma parte do xml ou do xml inteiro deve ser de 1,5MB, ou transformado em string, a propriedade Length deverá ser menor que 1572864 caracteres.
O retorno da primeira chamada irá retornar um xml em string ou não, dependendo do método, o 'GUID' terá de ser extraído de dentro da tag 'Mensagem'.


Resposta


Existem dois métodos para enviar o xml em partes que diferem pelo seu retorno: o método IntegraXml retorna um xml e o método IntegraXmlString retorna o xml no formato de string.


Exemplo do retorno em forma de xml do método IntegraXml:

<?xml version="1.0" encoding="utf-8"?>
<SOAP-ENV:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:HNS="http://tempuri.org/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:v1="http://tempuri.org/">
<SOAP-ENV:Header>
<ROClientIDHeader SOAP-ENV:mustUnderstand="0" xmlns="urn:DefaultLibrary">
<ID>{79F10A36-B949-4D29-8259-DFB6DE03BD50}</ID>
</ROClientIDHeader>
</SOAP-ENV:Header>
<SOAP-ENV:Body xmlns:ro="http://tempuri.org/">
<v1:MegaIntegradorService___IntegraXMLPartesResponse>
<v1:Result>
<v1:Erro>false</v1:Erro>
<v1:Mensagem>{17CD37B8-6929-458E-9596-7DE71761D758}</v1:Mensagem>
<v1:CodTransacao>0</v1:CodTransacao>
<v1:PKMega>
</v1:PKMega>
</v1:Result>
</v1:MegaIntegradorService___IntegraXMLPartesResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Exemplo do retorno em forma de string do método IntegraXmlString:

<?xml version="1.0" encoding="utf-8"?>
<SOAP-ENV:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:HNS="http://tempuri.org/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:v1="http://tempuri.org/">
<SOAP-ENV:Header>
<ROClientIDHeader SOAP-ENV:mustUnderstand="0" xmlns="urn:DefaultLibrary">
<ID>{3C441095-BE6A-48DE-A7D8-89380452F11D}</ID>
</ROClientIDHeader>
</SOAP-ENV:Header>
<SOAP-ENV:Body xmlns:ro="http://tempuri.org/">
<v1:MegaIntegradorService___IntegraXMLPartesStringResponse>
<v1:Result>&lt;Resultado&gt;&lt;Erro&gt;False&lt;/Erro&gt;&lt;Mensagem&gt;{5512BC3A-1FB4-41B3-960A-A15D39D0B1CC}&lt;/Mensagem&gt;&lt;CodTransacao&gt;0&lt;/CodTransacao&gt;&lt;PKMega&gt;&lt;/PKMega&gt;&lt;/Resultado&gt;</v1:Result>
</v1:MegaIntegradorService___IntegraXMLPartesStringResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>


Exemplos


Implementação em C# .NET.


Consumindo em C#


Nos links abaixo são exibidos códigos fontes de exemplos, onde é feita uma chamada utilizando a classe IntegradorRequestSoap, que é encarregada de fazer a chamada SOAP. 


Chamada


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
 
namespace Mega.Integrador.WebRequest.Soap
{
    public class MegaIntegradorClient
    {
 
        public XmlDocument IntegraXML(string pServidor, int pPorta, int pPRO_IN_CODIGO, int pUSU_IN_CODIGO, string pXML, string pXMLHeader, string pObs, string pEnviaRecebe, int pTransacao = 0, int ptimeOut = 360000)
        {
            Mega.Integrador.WebRequest.Soap.IntegradorRequestSoap request = new IntegradorRequestSoap();
            string metodo = "IntegraXML";
            string responsePrimeiroParte = String.Empty;
            string response = String.Empty;
            var partesXML = request.QuebraString(pXML);
            
            if(partesXML.Count > 1)
            {
                metodo = "IntegraXMLPartes";
                responsePrimeiroParte = request.CallWebService(pServidor, pPorta, pPRO_IN_CODIGO, pUSU_IN_CODIGO, partesXML[0], pXMLHeader, pObs, pEnviaRecebe, pTransacao, ptimeOut, metodo,"",true);
                int indexInicioAux = responsePrimeiroParte.IndexOf("<v1:Mensagem>");
                int indexFimAux = responsePrimeiroParte.IndexOf("</v1:Mensagem>");
                responsePrimeiroParte = responsePrimeiroParte.Substring(indexInicioAux, indexFimAux - indexInicioAux).Replace("<v1:Mensagem>", "").Replace("</v1:Mensagem>", "");
           
 
                for (int i = 1; i < partesXML.Count - 1; i++)
                {
                    request.CallWebService(pServidor, pPorta, pPRO_IN_CODIGO, pUSU_IN_CODIGO, partesXML[i], pXMLHeader, pObs, pEnviaRecebe, pTransacao, ptimeOut, metodo, responsePrimeiroParte,false,i + 1);
                }
 
                response = request.CallWebService(pServidor, pPorta, pPRO_IN_CODIGO, pUSU_IN_CODIGO, partesXML[partesXML.Count - 1], pXMLHeader, pObs, pEnviaRecebe, pTransacao, ptimeOut, metodo, responsePrimeiroParte, false, partesXML.Count, true);                
            }
            else
            {
                response = request.CallWebService(pServidor, pPorta, pPRO_IN_CODIGO, pUSU_IN_CODIGO, pXML, pXMLHeader, pObs, pEnviaRecebe, pTransacao, ptimeOut, metodo);
            }
            XmlDocument responseDocXml = new XmlDocument();
            responseDocXml.LoadXml(response);
            return responseDocXml;
        }
 
        public string IntegraXMLString(string pServidor, int pPorta, int pPRO_IN_CODIGO, int pUSU_IN_CODIGO, string pXML, string pXMLHeader, string pObs, string pEnviaRecebe, int pTransacao = 0, int ptimeOut = 360000)
        {
            Mega.Integrador.WebRequest.Soap.IntegradorRequestSoap request = new IntegradorRequestSoap();
            string metodo = "IntegraXMLString";
            string responsePrimeiroParte = String.Empty;
            string response = String.Empty;
            var partesXML = request.QuebraString(pXML);
          
            if(partesXML.Count > 1)
            {
                metodo = "IntegraXMLPartesString";
                responsePrimeiroParte = request.CallWebService(pServidor, pPorta, pPRO_IN_CODIGO, pUSU_IN_CODIGO, partesXML[0], pXMLHeader, pObs, pEnviaRecebe, pTransacao, ptimeOut, metodo, "", true);
                int indexInicioAux = responsePrimeiroParte.IndexOf("<v1:Mensagem>");
                
                if (indexInicioAux < 0)
                    indexInicioAux = responsePrimeiroParte.IndexOf("Mensagem&gt;");
    
                int indexFimAux = responsePrimeiroParte.IndexOf("</v1:Mensagem>");
                if (indexFimAux < 0)
                    indexFimAux = responsePrimeiroParte.IndexOf("&lt;/Mensagem&gt");
 
                responsePrimeiroParte = responsePrimeiroParte.Substring(indexInicioAux, indexFimAux - indexInicioAux).Replace("<v1:Mensagem>", "").Replace("</v1:Mensagem>", "").Replace("Mensagem&gt;", "").Replace("&lt;/Mensagem&gt", "");
 
                for (int i = 1; i < partesXML.Count - 1; i++)
                {
                    request.CallWebService(pServidor, pPorta, pPRO_IN_CODIGO, pUSU_IN_CODIGO, partesXML[i], pXMLHeader, pObs, pEnviaRecebe, pTransacao, ptimeOut, metodo, responsePrimeiroParte, false, i + 1);
                }
 
                response = request.CallWebService(pServidor, pPorta, pPRO_IN_CODIGO, pUSU_IN_CODIGO, partesXML[partesXML.Count - 1], pXMLHeader, pObs, pEnviaRecebe, pTransacao, ptimeOut, metodo, responsePrimeiroParte, false, partesXML.Count, true);        
                
            }
            else
            {               
                response = request.CallWebService(pServidor, pPorta, pPRO_IN_CODIGO, pUSU_IN_CODIGO, pXML, pXMLHeader, pObs, pEnviaRecebe, pTransacao, ptimeOut, metodo);
            }
            int indexInicio = response.IndexOf("<v1:Result>");
            int indexFim = response.IndexOf("</v1:Result>");
            return response.Substring(indexInicio, indexFim - indexInicio).Replace("v1:","");
        }
    }
}


Fonte da classe IntegradorRequestSoap


Classe encarregada de montar o pacote da chamada SOAP e consumir o webservice, devolvendo uma string com o xml do resultado:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Xml;
using System.IO;
using System.Net;
 
namespace Mega.Integrador.WebRequest.Soap
{
    public classIntegradorRequestSoap
    {
 
        internal string CallWebService(string pServidor, int pPorta, int pPRO_IN_CODIGO, int pUSU_IN_CODIGO, string pXML, string pXMLHeader, string pObs, string pEnviaRecebe, int pTransacao = 0, int pTimeOut = 360000, string pMetodo = "IntegraXML", string pGuidMedateXml = "", bool pPrimeiraParte = false, int pNumeroParte = 1, bool pUltimaParte = false)
        {
            var _url = "http://" + pServidor + ":" + pPorta.ToString() + "/Integrador";
            var _action = pMetodo;
 
            XmlDocument soapEnvelopeXml = CreateSoapEnvelope(pPRO_IN_CODIGO, pUSU_IN_CODIGO, pXML, pXMLHeader, pObs, pEnviaRecebe, pTransacao, pMetodo, pGuidMedateXml, pPrimeiraParte, pNumeroParte, pUltimaParte );
            HttpWebRequest webRequest = CreateWebRequest(_url, _action, pTimeOut);
            InsertSoapEnvelopeIntoWebRequest(soapEnvelopeXml, webRequest);
 
            //Início do web request assíncrono.
            IAsyncResult asyncResult = webRequest.BeginGetResponse(null, null);           
            
            asyncResult.AsyncWaitHandle.WaitOne();
            
            //Recuperando a resposta da requisição web completa. 
            string soapResult;
            using (WebResponse webResponse = webRequest.EndGetResponse(asyncResult))
            {
                using (StreamReader rd = new StreamReader(webResponse.GetResponseStream()))
                {
                    soapResult = rd.ReadToEnd();
                }
                Console.Write(soapResult);
                return soapResult;
            }
        }
 
 
        private HttpWebRequest CreateWebRequest(string url, string action, int timeOut)
        {
            HttpWebRequest webRequest = (HttpWebRequest)System.Net.WebRequest.Create(url);
            webRequest.Headers.Add("SOAPAction", action);
            webRequest.ContentType = "application/x-www-form-urlencoded";        
            webRequest.Accept = "text/xml";
            webRequest.Method = "POST";
            webRequest.Timeout = timeOut;
            return webRequest;
        }
 
        private XmlDocument CreateSoapEnvelope(int pPRO_IN_CODIGO, int pUSU_IN_CODIGO, string pXML, string pXMLHeader, string pObs, string pEnviaRecebe, int pTransacao, string metodo = "IntegraXML", string pGuidMedateXml = "", bool pPrimeiraParte = false, int pNumeroParte = 1, bool pUltimaParte = false)
        {            
            XmlDocument soapEnvelop = new XmlDocument();
 
            StringBuilder str = new StringBuilder();
            str.AppendLine("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
            str.AppendLine("<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\"");
            str.AppendLine("xmlns:xsi=\"http://www.w3.org/1999/XMLSchema-instance\"");
            str.AppendLine("xmlns:xsd=\"http://www.w3.org/1999/XMLSchema\"> ");
            str.AppendLine("<SOAP-ENV:Body>");
            str.AppendLine("<" + metodo + " xmlns=\"MegaIntegradorService\"");
            str.AppendLine("SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">");
            str.AppendLine("<pPRO_IN_ID xsi:type=\"xsd:integer\">" + pPRO_IN_CODIGO.ToString() + "</pPRO_IN_ID>");
            str.AppendLine("<pUSU_IN_CODIGO xsi:type=\"xsd:integer\">" + pUSU_IN_CODIGO.ToString() + "</pUSU_IN_CODIGO>");                      
            str.AppendLine("<pXML xsi:type=\"xsd:string\"><![CDATA[" + pXML + "]]></pXML>"); 
 
            if (metodo == "IntegraXMLPartes" || metodo == "IntegraXMLPartesString")                           
                str.AppendLine("<pGuidFile xsi:type=\"xsd:string\">" + pGuidMedateXml + "</pGuidFile>");
                        
            str.AppendLine("<pXMLHeader xsi:type=\"xsd:string\"> " + pXMLHeader + "</pXMLHeader>");
            str.AppendLine("<pObs xsi:type=\"xsd:string\">" + pObs + "</pObs>");
            str.AppendLine("<pEnviaRecebe xsi:type=\"xsd:string\">" + pEnviaRecebe + "</pEnviaRecebe>");
            str.AppendLine("<pTransacao xsi:type=\"xsd:integer\">" + pTransacao.ToString() + "</pTransacao> ");
 
            if (metodo == "IntegraXMLPartes" || metodo == "IntegraXMLPartesString")
            {
                str.AppendLine("<pPrimeiraParte xsi:type=\"xsd:boolean\">" + Convert.ToInt32(pPrimeiraParte).ToString() + "</pPrimeiraParte> ");
                str.AppendLine("<pNumeroParte xsi:type=\"xsd:integer\">" + pNumeroParte.ToString() + "</pNumeroParte> ");
                str.AppendLine("<pUltimaParte xsi:type=\"xsd:boolean\">" + Convert.ToInt32(pUltimaParte).ToString() + "</pUltimaParte> ");
            }
            
            str.AppendLine("</" + metodo + ">");
            str.AppendLine("</SOAP-ENV:Body>");
            str.AppendLine("</SOAP-ENV:Envelope>");
 
            soapEnvelop.LoadXml(str.ToString());
            return soapEnvelop;
        }
 
        private void InsertSoapEnvelopeIntoWebRequest(XmlDocument soapEnvelopeXml, HttpWebRequest webRequest)
        {
            using (Stream stream = webRequest.GetRequestStream())
            {
                soapEnvelopeXml.Save(stream);
            }
        }
        
 
        public List<string> QuebraString(string pXml)
        {
            int tamanhoLimitParteXml = 1572864;// ~ 1,5Mb
                                       
            List<string> resultado = new List<string>();
 
          
            if (pXml.Length > tamanhoLimitParteXml)
            {
                int partes = pXml.Length / tamanhoLimitParteXml;
              
                int restoDivisao = pXml.Length % tamanhoLimitParteXml;
 
                if (restoDivisao > 0)
                    partes++;
 
                resultado.Add(pXml.Substring(0, tamanhoLimitParteXml));
 
                for (int vContador = 1; vContador < partes - 1; vContador++)
                {
                    resultado.Add(pXml.Substring(tamanhoLimitParteXml * vContador, tamanhoLimitParteXml));
                }
 
                int inicioUltimaParte = tamanhoLimitParteXml * (partes - 1);
                resultado.Add(pXml.Substring(inicioUltimaParte, pXml.Length - inicioUltimaParte));             
                
            }
            else
                resultado.Add(pXml);
 
            return resultado;
        }
    }
}