Il client invia la richiesta SOAP e riceve la risposta


159

Tentativo di creare un client C # (verrà sviluppato come servizio Windows) che invia richieste SOAP a un servizio Web (e ottiene i risultati).

Da questa domanda ho visto questo codice:

protected virtual WebRequest CreateRequest(ISoapMessage soapMessage)
{
    var wr = WebRequest.Create(soapMessage.Uri);
    wr.ContentType = "text/xml;charset=utf-8";
    wr.ContentLength = soapMessage.ContentXml.Length;

    wr.Headers.Add("SOAPAction", soapMessage.SoapAction);
    wr.Credentials = soapMessage.Credentials;
    wr.Method = "POST";
    wr.GetRequestStream().Write(Encoding.UTF8.GetBytes(soapMessage.ContentXml), 0, soapMessage.ContentXml.Length);

    return wr;
}

public interface ISoapMessage
{
    string Uri { get; }
    string ContentXml { get; }
    string SoapAction { get; }
    ICredentials Credentials { get; }
}

Sembra carino, qualcuno sa come usarlo e se è la migliore pratica?

Risposte:


224

Normalmente uso un altro modo per fare lo stesso

using System.Xml;
using System.Net;
using System.IO;

public static void CallWebService()
{
    var _url = "http://xxxxxxxxx/Service1.asmx";
    var _action = "http://xxxxxxxx/Service1.asmx?op=HelloWorld";

    XmlDocument soapEnvelopeXml = CreateSoapEnvelope();
    HttpWebRequest webRequest = CreateWebRequest(_url, _action);
    InsertSoapEnvelopeIntoWebRequest(soapEnvelopeXml, webRequest);

    // begin async call to web request.
    IAsyncResult asyncResult = webRequest.BeginGetResponse(null, null);

    // suspend this thread until call is complete. You might want to
    // do something usefull here like update your UI.
    asyncResult.AsyncWaitHandle.WaitOne();

    // get the response from the completed web request.
    string soapResult;
    using (WebResponse webResponse = webRequest.EndGetResponse(asyncResult))
    {
        using (StreamReader rd = new StreamReader(webResponse.GetResponseStream()))
        {
            soapResult = rd.ReadToEnd();
        }
        Console.Write(soapResult);        
    }
}

private static HttpWebRequest CreateWebRequest(string url, string action)
{
    HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url);
    webRequest.Headers.Add("SOAPAction", action);
    webRequest.ContentType = "text/xml;charset=\"utf-8\"";
    webRequest.Accept = "text/xml";
    webRequest.Method = "POST";
    return webRequest;
}

private static XmlDocument CreateSoapEnvelope()
{
    XmlDocument soapEnvelopeDocument = new XmlDocument();
    soapEnvelopeDocument.LoadXml(
    @"<SOAP-ENV:Envelope xmlns:SOAP-ENV=""http://schemas.xmlsoap.org/soap/envelope/"" 
               xmlns:xsi=""http://www.w3.org/1999/XMLSchema-instance"" 
               xmlns:xsd=""http://www.w3.org/1999/XMLSchema"">
        <SOAP-ENV:Body>
            <HelloWorld xmlns=""http://tempuri.org/"" 
                SOAP-ENV:encodingStyle=""http://schemas.xmlsoap.org/soap/encoding/"">
                <int1 xsi:type=""xsd:integer"">12</int1>
                <int2 xsi:type=""xsd:integer"">32</int2>
            </HelloWorld>
        </SOAP-ENV:Body>
    </SOAP-ENV:Envelope>");
    return soapEnvelopeDocument;
}

private static void InsertSoapEnvelopeIntoWebRequest(XmlDocument soapEnvelopeXml, HttpWebRequest webRequest)
{
    using (Stream stream = webRequest.GetRequestStream())
    {
        soapEnvelopeXml.Save(stream);
    }
}

1
È samething, ma ho messo tutto qui, inclusa la stringa di richiesta SOAP.
KBBScrivi il

5
ok, penso che tu debba metterlo nella richiesta SOAP, se hai un esempio di payload della richiesta, allora puoi costruire una richiesta proprio così. Non sei sicuro del tipo di sicurezza che usi, se stai utilizzando WS-Security, il nome utente e la password che puoi passare con l'intestazione della tua richiesta SOAP.
KBBScrivi il

3
Sto pensando a qualcosa del genere HttpWebRequest webRequest = CreateWebRequest (_url, _action); webRequest.Credentials = new NetworkCredential (nome utente, password, dominio);
Base di dati

3
@hamish: questo è solo uno snippet di codice concettuale. Non considerarlo come un codice di qualità della produzione.
KBBScrivi il

4
Estremamente utile e mi ha aiutato a lavorare usando Telerik Fiddler per inviare manualmente il POST al mio servizio web, perché ho potuto vedere tutte le intestazioni che hai impostato. Grazie mille.
Raddevus,

64

Ho questa semplice soluzione qui :

Invio di richieste SOAP e ricezione di risposte in .NET 4.0 C # senza utilizzare le classi proxy o WSDL:

class Program
    {
        /// <summary>
        /// Execute a Soap WebService call
        /// </summary>
        public static void Execute()
        {
            HttpWebRequest request = CreateWebRequest();
            XmlDocument soapEnvelopeXml = new XmlDocument();
            soapEnvelopeXml.LoadXml(@"<?xml version=""1.0"" encoding=""utf-8""?>
                <soap:Envelope xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/"">
                  <soap:Body>
                    <HelloWorld xmlns=""http://tempuri.org/"" />
                  </soap:Body>
                </soap:Envelope>");

            using (Stream stream = request.GetRequestStream())
            {
                soapEnvelopeXml.Save(stream);
            }

            using (WebResponse response = request.GetResponse())
            {
                using (StreamReader rd = new StreamReader(response.GetResponseStream()))
                {
                    string soapResult = rd.ReadToEnd();
                    Console.WriteLine(soapResult);
                }
            }
        }
        /// <summary>
        /// Create a soap webrequest to [Url]
        /// </summary>
        /// <returns></returns>
        public static HttpWebRequest CreateWebRequest()
        {
            HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(@"http://localhost:56405/WebService1.asmx?op=HelloWorld");
            webRequest.Headers.Add(@"SOAP:Action");
            webRequest.ContentType = "text/xml;charset=\"utf-8\"";
            webRequest.Accept = "text/xml";
            webRequest.Method = "POST";
            return webRequest;
        }

        static void Main(string[] args)
        {
            Execute();
        }
    }

Possiamo creare un client soap xml senza usare il sapone stringa xml. Con l'utilizzo del codice c #. Come: var request = (HttpWebRequest) WebRequest.Create (uri); request.Method = Common.Method; Ad esempio un metodo c # che crea più di un client soap xml ai diversi servizi wsdl con parametri.
Dvlpr,

Ricevo il seguente errore e il codice termina: "soap" è un prefisso non dichiarato. Linea 2, posizione 18. Mi manca qualcosa? La richiesta SOAP interfaccia utente per il mio webservice può essere trovato qui: stackoverflow.com/questions/50430398/...
Vesnog

Funziona con webRequest.Headers.Add("SOAPAction", "http://tempuri.org/.....");Controlla l'azione SOAP presente in SoapUI e usala.
Robert Koch,

Viene visualizzato un errore quando utilizzo i due punti nell'intestazione SOAPAction. Devo fare: webRequest.Headers.Add (@ "SOAPAction", "SomeAction");
Web degli sviluppatori

come file ricevuto e trasformare in PDF?
Leandro,

20

La migliore pratica è fare riferimento al WSDL e usarlo come riferimento al servizio web. È più facile e funziona meglio, ma se non si dispone del WSDL, le definizioni XSD sono un buon pezzo di codice.


1
Come posso aggiungere un'intestazione personalizzata per la richiesta SOAP Se aggiungo WSDL come riferimento del servizio Web e anche punti finali ???
BASEER HAIDER JAFRI,

12
Hai detto di fare questo, qualche riferimento su COME farlo?
Zapnologica,

Se WSDL non desidera un'intestazione personalizzata, non dovresti aggiungerne una.
StingyJack,

1
Fondamentalmente cosa è necessario per inviare - ricevere SAPONE? È sufficiente utilizzare l'associazione che supporta SOAP come wsHttpBinding e riferimento WSDL? Tutto il resto è come usare REST (chiamare metodi WCF, ricevere risposta)?
FrenkyB,

Sono d'accordo con i WSDL, il primo è molto più complesso e superfluo. Tutto ciò che serve è andare su Riferimenti di servizio nel progetto (nelle versioni precedenti di Visual Studio), fare clic con il tasto destro del mouse, aggiungere il riferimento al servizio e inserire i dettagli corretti. Viene creato un oggetto c # che deve essere creato come variabile. Tutte le funzionalità del servizio WSDL vengono quindi esposte tramite codice
lllllllllllllIllllIll

19

Penso che ci sia un modo più semplice:

 public async Task<string> CreateSoapEnvelope()
 {
      string soapString = @"<?xml version=""1.0"" encoding=""utf-8""?>
          <soap:Envelope xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/"">
              <soap:Body>
                  <HelloWorld xmlns=""http://tempuri.org/"" />
              </soap:Body>
          </soap:Envelope>";

          HttpResponseMessage response = await PostXmlRequest("your_url_here", soapString);
          string content = await response.Content.ReadAsStringAsync();

      return content;
 }

 public static async Task<HttpResponseMessage> PostXmlRequest(string baseUrl, string xmlString)
 {
      using (var httpClient = new HttpClient())
      {
          var httpContent = new StringContent(xmlString, Encoding.UTF8, "text/xml");
          httpContent.Headers.Add("SOAPAction", "http://tempuri.org/HelloWorld");

          return await httpClient.PostAsync(baseUrl, httpContent);
       }
 }

Funzionava come un campione. Ho aggiunto parametri al metodo CreateSoapEnvelope per poter passare la stringa XML, l'URL del post e l'URL dell'azione per rendere riutilizzabili i metodi ed era esattamente quello che stavo cercando.
Scivoloso Pete l'

migliore risposta per la mia opinione perché utilizza HttpClient più pertinente anziché WebResponse obsoleto.
Akmal Salikhov

15

Ho scritto una classe di supporto più generale che accetta un dizionario basato su stringhe di parametri personalizzati, in modo che possano essere impostati dal chiamante senza doverli codificare. Inutile dire che è necessario utilizzare tale metodo solo quando si desidera (o è necessario) emettere manualmente un servizio Web basato su SOAP: negli scenari più comuni l'approccio consigliato sarebbe utilizzare il servizio Web WSDL insieme al riferimento al servizio Aggiungi Visual Studio caratteristica invece.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Xml;

namespace Ryadel.Web.SOAP
{
    /// <summary>
    /// Helper class to send custom SOAP requests.
    /// </summary>
    public static class SOAPHelper
    {
        /// <summary>
        /// Sends a custom sync SOAP request to given URL and receive a request
        /// </summary>
        /// <param name="url">The WebService endpoint URL</param>
        /// <param name="action">The WebService action name</param>
        /// <param name="parameters">A dictionary containing the parameters in a key-value fashion</param>
        /// <param name="soapAction">The SOAPAction value, as specified in the Web Service's WSDL (or NULL to use the url parameter)</param>
        /// <param name="useSOAP12">Set this to TRUE to use the SOAP v1.2 protocol, FALSE to use the SOAP v1.1 (default)</param>
        /// <returns>A string containing the raw Web Service response</returns>
        public static string SendSOAPRequest(string url, string action, Dictionary<string, string> parameters, string soapAction = null, bool useSOAP12 = false)
        {
            // Create the SOAP envelope
            XmlDocument soapEnvelopeXml = new XmlDocument();
            var xmlStr = (useSOAP12)
                ? @"<?xml version=""1.0"" encoding=""utf-8""?>
                    <soap12:Envelope xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance""
                      xmlns:xsd=""http://www.w3.org/2001/XMLSchema""
                      xmlns:soap12=""http://www.w3.org/2003/05/soap-envelope"">
                      <soap12:Body>
                        <{0} xmlns=""{1}"">{2}</{0}>
                      </soap12:Body>
                    </soap12:Envelope>"
                : @"<?xml version=""1.0"" encoding=""utf-8""?>
                    <soap:Envelope xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/"" 
                        xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" 
                        xmlns:xsd=""http://www.w3.org/2001/XMLSchema"">
                        <soap:Body>
                           <{0} xmlns=""{1}"">{2}</{0}>
                        </soap:Body>
                    </soap:Envelope>";
            string parms = string.Join(string.Empty, parameters.Select(kv => String.Format("<{0}>{1}</{0}>", kv.Key, kv.Value)).ToArray());
            var s = String.Format(xmlStr, action, new Uri(url).GetLeftPart(UriPartial.Authority) + "/", parms);
            soapEnvelopeXml.LoadXml(s);

            // Create the web request
            HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url);
            webRequest.Headers.Add("SOAPAction", soapAction ?? url);
            webRequest.ContentType = (useSOAP12) ? "application/soap+xml;charset=\"utf-8\"" : "text/xml;charset=\"utf-8\"";
            webRequest.Accept = (useSOAP12) ? "application/soap+xml" : "text/xml";
            webRequest.Method = "POST";

            // Insert SOAP envelope
            using (Stream stream = webRequest.GetRequestStream())
            {
                soapEnvelopeXml.Save(stream);
            }

            // Send request and retrieve result
            string result;
            using (WebResponse response = webRequest.GetResponse())
            {
                using (StreamReader rd = new StreamReader(response.GetResponseStream()))
                {
                    result = rd.ReadToEnd();
                }
            }
            return result;
        }
    }
}

Per ulteriori informazioni e dettagli su questa lezione puoi anche leggere questo post sul mio blog.


1

Quindi questo è il mio codice finale dopo aver cercato su Google per 2 giorni su come aggiungere uno spazio dei nomi ed effettuare una richiesta soap insieme alla busta SOAP senza aggiungere proxy / riferimento di servizio

class Request
{
    public static void Execute(string XML)
    {
        try
        {
            HttpWebRequest request = CreateWebRequest();
            XmlDocument soapEnvelopeXml = new XmlDocument();
            soapEnvelopeXml.LoadXml(AppendEnvelope(AddNamespace(XML)));

            using (Stream stream = request.GetRequestStream())
            {
                soapEnvelopeXml.Save(stream);
            }

            using (WebResponse response = request.GetResponse())
            {
                using (StreamReader rd = new StreamReader(response.GetResponseStream()))
                {
                    string soapResult = rd.ReadToEnd();
                    Console.WriteLine(soapResult);
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex);
        }
    }

    private static HttpWebRequest CreateWebRequest()
    {
        string ICMURL = System.Configuration.ConfigurationManager.AppSettings.Get("ICMUrl");
        HttpWebRequest webRequest = null;

        try
        {
            webRequest = (HttpWebRequest)WebRequest.Create(ICMURL);
            webRequest.Headers.Add(@"SOAP:Action");
            webRequest.ContentType = "text/xml;charset=\"utf-8\"";
            webRequest.Accept = "text/xml";
            webRequest.Method = "POST";
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex);
        }
        return webRequest;
    }

    private static string AddNamespace(string XML)
    {
        string result = string.Empty;
        try
        {

            XmlDocument xdoc = new XmlDocument();
            xdoc.LoadXml(XML);

            XmlElement temproot = xdoc.CreateElement("ws", "Request", "http://example.com/");
            temproot.InnerXml = xdoc.DocumentElement.InnerXml;
            result = temproot.OuterXml;

        }
        catch (Exception ex)
        {
            Console.WriteLine(ex);
        }

        return result;
    }

    private static string AppendEnvelope(string data)
    {
        string head= @"<soapenv:Envelope xmlns:soapenv=""http://schemas.xmlsoap.org/soap/envelope/"" ><soapenv:Header/><soapenv:Body>";
        string end = @"</soapenv:Body></soapenv:Envelope>";
        return head + data + end;
    }
}

-5

Chiama il servizio web SOAP in c #

using (var client = new UpdatedOutlookServiceReferenceAPI.OutlookServiceSoapClient("OutlookServiceSoap"))
{
    ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls12;
    var result = client.UploadAttachmentBase64(GUID, FinalFileName, fileURL);

    if (result == true)
    {
        resultFlag = true;
    }
    else
    {
        resultFlag = false;
    }
    LogWriter.LogWrite1("resultFlag : " + resultFlag);
}

3
Che cosa è new UpdatedOutlookServiceReferenceAPI.OutlookServiceSoapClient()?
Chris F Carroll,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.