menu di navigazione del network

MTOM è sempre un requisito?

Ciao a tutti,
sapete dirmi se MTOM è ancora un requisito per SDICOOP o nell’anno trascorso sono entrati nel nuovo secolo anche loro e ora se ne può fare a meno?

Perchè non posso più rimandare di portare la mia applicazione da .NET a .NET Core, e quello che crea più problemi è che AGED richiede MTOM, abbandonato da tempo da un produttore marginale di piattaforme di sviluppo quale è Microsoft…
Altrimenti mi tocca separare in applicazioni diverse le parti, e devo lavorare tantissimo solo per fare felice IBM… :frowning:
O qualcuno ha messo a punto un modo per fare le chiamate da .NET Core?

grazie

Sì è ancora un requisito…e credo che ormai c’è lo teniamo, non mi immagino rivoluzioni così importanti sulle modalità di comunicazioni (impensabile: nuove fasi di test? “io questo non creto” cit.), al massimo qualche cambio di formato negli xml che mandano e minor fix.

Ahimè ti capisco benissimo, anch’io sono nella stessa situazione…ho un po’ di progetti “a se” in .net con le funzionalità minime per interagire con lo SDI ed il resto in Core :frowning: (su stackoverflow non ho trovato nulla per utilizzare il core per le chiamate MTOM, ergo non esiste :smiley: )

che strazio…
anche perchè a tenerle separate poi devo coordinarle, autorizzarli l’uno con l’altro ecc… una architettura a microservizi solo per parlare con un cavolo di WS, bleah
ho trovato questa accrocchiata, solo per le chiamate in uscita (che mi basterebbero, quelle in entrata le avevo già scorporate su un WS a parte per lo stesso motivo) ma non mi convince molto: https://github.com/lennykean/WcfCoreMtomEncoder

Parlano proprio di noi:

Non sviluppo in .Net quindi mi sto solo impicciando, ma date un occhio all’ultima risposta e ai link cui rimanda, magari vi è utile.

rimanda alla fine a quello stesso codice che avevo segnalato io…

Nell’ultimo post si dice che un membro di. Net core indichi una implementazione migliore di quella da te linkata (che è nel penultimo post) e si fa riferimento a questo link:

Mi riferivo a questo

1 Like

ho gettato la spugna e sto gestendo con servizi diversi distribuiti… bleah

Ciao a tutti,
condivido a beneficio della comunità il codice sorgente per NET CORE che da noi ha mandato centomila fatture. Mi sembra assurdo che dobbiate ammazzarvi a fare servizi e controservizi che si palleggiano per una mancanza di NET CORE.
La PleaseSendItToSdiAsync si potrà poi utilizzare se e quando in NET CORE metteranno MTOM; noi utilizziamo la funzione PleasSendItToSdiAsync2 che è artigianale oltre il lecito ma funziona.
Le chiamate usano RestSharp e vengono usate le strutture create attraverso il riferimento a SdIRiceviFile_v1.0.wsdl
che chiunque dovrebbe riuscire a reperire.
Chiedo umilmente scusa pubblicamente a @ivan.barbato al quale avevo promesso mesi fa il tutto, lo cito in modo che possa vedere per primo questo link.

protected async Task<rispostaSdIRiceviFile_Type> PleaseSendItToSdiAsync(fileSdIBase_Type requestData, string serviceUrl_riceviFile, string certificatePath_riceviFile, string certificatePwd_riceviFile)
            {
                var newEP = new System.ServiceModel.EndpointAddress(new Uri(serviceUrl_riceviFile));

                var newBind = new System.ServiceModel.BasicHttpBinding(System.ServiceModel.BasicHttpSecurityMode.Transport);
                newBind.Security.Transport.ClientCredentialType = System.ServiceModel.HttpClientCredentialType.Certificate;
                //newBind.MessageEncoding = System.ServiceModel.WSMessageEncoding.Mtom;
                var certificate = new X509Certificate2(System.IO.File.ReadAllBytes(certificatePath_riceviFile), certificatePwd_riceviFile, X509KeyStorageFlags.MachineKeySet);

                using (System.ServiceModel.ChannelFactory<SdIRiceviFileChannel> factory =
                    new System.ServiceModel.ChannelFactory<SdIRiceviFileChannel>(newBind, newEP))
                {
                    factory.Credentials.ClientCertificate.Certificate = certificate;
                    using (var channel = factory.CreateChannel())
                    {
                        var request = new RiceviFileRequest(requestData);
                        RiceviFileResponse responseMessage = await channel.RiceviFileAsync(request);
                        return responseMessage.rispostaSdIRiceviFile;
                    }
                }
            }

            protected async Task<rispostaSdIRiceviFile_Type> PleaseSendItToSdiAsync2(fileSdIBase_Type requestData, string serviceUrl_riceviFile, string certificatePath_riceviFile, string certificatePwd_riceviFile)
            {
                var cert = new X509Certificate2(certificatePath_riceviFile, certificatePwd_riceviFile, X509KeyStorageFlags.UserKeySet);
                var client = new RestClient(serviceUrl_riceviFile)
                {
                    ClientCertificates = new X509CertificateCollection
                    {
                        cert
                    }
                };


                var request = new RestRequest(Method.POST);

                request.AddHeader("accept", "text/plain");
                request.AddHeader("content-type", "text/xml");

                // create parameter
                var serializer = new XmlSerializer(typeof(RiceviFileRequest));

                var requestParameter = new RiceviFileRequest(requestData);

                string requestParameterStr;

                var namepsaces = new XmlSerializerNamespaces(new[] { XmlQualifiedName.Empty });
                var settings = new XmlWriterSettings { Indent = true, OmitXmlDeclaration = true, NamespaceHandling = NamespaceHandling.OmitDuplicates }; // some parameters to make it clean, only OmitXmlDeclaration is mandatory 
                using (var stringWriter = new StringWriter())
                {
                    using (var xmlWriter = XmlWriter.Create(stringWriter, settings))
                    {
                        serializer.Serialize(xmlWriter, requestParameter, namepsaces);
                        requestParameterStr = stringWriter.ToString();
                    }
                }

                // patch parameter to add the namespace prefix required by consumer service
                requestParameterStr = requestParameterStr.Replace("<fileSdIAccoglienza>", "<fileSdIAccoglienza xmlns=\"http://www.fatturapa.gov.it/sdi/ws/trasmissione/v1.0/types\">");
                requestParameterStr = requestParameterStr.Replace("<NomeFile>", "<NomeFile xmlns=\"\">");
                requestParameterStr = requestParameterStr.Replace("<File>", "<File xmlns=\"\">");
                requestParameterStr = requestParameterStr.Replace("<RiceviFileRequest>", "");
                requestParameterStr = requestParameterStr.Replace("</RiceviFileRequest>", "");
                requestParameterStr = requestParameterStr.Replace("\r", "");
                requestParameterStr = requestParameterStr.Replace("\n", "");

                // wrap parameter in a soap envelop
                requestParameterStr =
                    $"<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\"><s:Header/><s:Body xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">{requestParameterStr}</s:Body></s:Envelope>";
                request.AddParameter(
                    "text/xml",
                    requestParameterStr,
                    ParameterType.RequestBody);
                ServicePointManager.ServerCertificateValidationCallback = (a, b, c, d) => true;
                var response = client.Execute(request);
                if (!response.IsSuccessful)
                {
                    if (response.ErrorException != null)
                        throw response.ErrorException;
                    else
                        throw new Exception(response.ErrorMessage);
                }
                var mtomMsg = response.Content;

                // remove MTOM elements from the received Content. here comes the ugly part ^^
                /*
                 var responseContentType = response.ContentType;
                 var contentTypeElements = responseContentType.Split(";");
                 var boundary = contentTypeElements.FirstOrDefault(x => x.TrimStart().StartsWith("boundary="))?.Trim().Substring("boundary=".Length);
                 var startElement = contentTypeElements.FirstOrDefault(x => x.TrimStart().StartsWith("start="))?.Trim().Substring("start=".Length);
                 boundary = boundary.Trim('"');
                 startElement = startElement.Trim('"');

                 var startIndex = mtomMsg.IndexOf(startElement) + startElement.Length;
                 var endIndex = mtomMsg.LastIndexOf("--" + boundary + "--", startIndex);
                 */
                var startsoapenv = mtomMsg.IndexOf("<soapenv:Envelope");
                var endsoapenv = mtomMsg.IndexOf("</soapenv:Envelope>");
                var cleanedMtomMsg = mtomMsg.Substring(startsoapenv, endsoapenv - startsoapenv + 19);

                // Get the result inside the Soap envelop
                var soapDocument = XDocument.Parse(cleanedMtomMsg);

                var envelopeElt = soapDocument.Root;
                var bodyElt = (System.Xml.Linq.XElement)envelopeElt.FirstNode;
                var responseStr = bodyElt.FirstNode.ToString();

                var ret = new rispostaSdIRiceviFile_Type();
                var fn = (System.Xml.Linq.XElement)(bodyElt.FirstNode);
                foreach (var node in fn.DescendantNodes())
                {
                    if (node is XElement ne)
                    {
                        if (String.Equals(ne.Name.LocalName, "IdentificativoSdI",
                            StringComparison.CurrentCultureIgnoreCase))
                            ret.IdentificativoSdI = ne.Value;
                        else if (String.Equals(ne.Name.LocalName, "DataOraRicezione", StringComparison.CurrentCultureIgnoreCase))
                        {
                            if (DateTime.TryParse(ne.Value, out DateTime dt))
                                ret.DataOraRicezione = dt.ToUniversalTime();
                        }
                        else if (String.Equals(ne.Name.LocalName, "Errore", StringComparison.CurrentCultureIgnoreCase))
                        {
                            if (Enum.TryParse<erroreInvio_Type>(ne.Value, out erroreInvio_Type valore))
                            {
                                ret.Errore = valore;
                            }
                        }

                        else if (String.Equals(ne.Name.LocalName, "ErroreSpecified", StringComparison.CurrentCultureIgnoreCase))
                            ret.ErroreSpecified = bool.Parse(ne.Value);
                    }
                }

                return await Task.FromResult(ret);
            }
3 Likes