Klien akan mengirim permintaan SOAP dan menerima tanggapan


159

Mencoba membuat klien C # (akan dikembangkan sebagai layanan Windows) yang mengirimkan permintaan SOAP ke layanan web (dan mendapatkan hasilnya).

Dari pertanyaan ini saya melihat kode ini:

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; }
}

Terlihat bagus, ada yang tahu cara menggunakannya dan apakah itu praktik terbaik?

Jawaban:


224

Saya biasanya menggunakan cara lain untuk melakukan hal yang sama

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
Itu sama, Tapi saya telah meletakkan semuanya di sini, termasuk string permintaan SABUN.
KBBWrite

5
ok, saya pikir Anda harus memasukkannya ke dalam permintaan SOAP, jika Anda memiliki sampel payload permintaan, maka Anda dapat membangun permintaan begitu saja. Tidak yakin jenis keamanan apa yang Anda gunakan, Jika Anda menggunakan WS-Security maka nama pengguna dan kata sandi yang Anda bisa berikan dengan Header permintaan SOAP Anda.
KBBWrite

3
Saya sedang memikirkan sesuatu seperti ini HttpWebRequest webRequest = CreateWebRequest (_url, _action); webRequest.Credentials = new NetworkCredential (nama pengguna, kata sandi, domain);
Data-Base

3
@hamish: ini hanya cuplikan kode konseptual. Jangan menganggapnya sebagai kode kualitas produksi.
KBBWrite

4
Sangat membantu dan membantu saya bekerja dengan menggunakan Telerik Fiddler untuk POST manual ke layanan web saya, karena saya bisa melihat semua header yang Anda atur. Terima kasih banyak.
raddevus

64

Saya mendapat solusi sederhana ini di sini :

Mengirim permintaan SOAP dan menerima respons dalam .NET 4.0 C # tanpa menggunakan kelas WSDL atau proxy:

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();
        }
    }

Bisakah kita membuat klien xml sabun tanpa menggunakan string xml sabun. Dengan menggunakan kode c #. Seperti sebagai: var request = (HttpWebRequest) WebRequest.Create (uri); request.Method = Common.Method; Misalnya satu metode c # yang menciptakan lebih dari satu klien xml sabun ke berbagai layanan wsdl dengan parameter.
Dvlpr

Saya mendapatkan kesalahan berikut dan kode berakhir: 'sabun' adalah awalan yang tidak dideklarasikan. Baris 2, posisi 18. Apakah saya melewatkan sesuatu? Permintaan SOAP UI untuk layanan web saya dapat ditemukan di sini: stackoverflow.com/questions/50430398/…
Vesnog

Bekerja dengan webRequest.Headers.Add("SOAPAction", "http://tempuri.org/.....");Periksa Aksi SABUN yang ada di SoapUI dan gunakan itu.
Robert Koch

Saya mendapatkan kesalahan ketika saya menggunakan titik dua di header SOAPAction. Yang harus saya lakukan: webRequest.Headers.Add (@ "SOAPAction", "SomeAction");
Pengembang Web

bagaimana menerima file dan mentransformasikannya dalam PDF?
Leandro

20

Praktik terbaik adalah merujuk WSDL dan menggunakannya seperti referensi layanan web. Lebih mudah dan berfungsi lebih baik, tetapi jika Anda tidak memiliki WSDL, definisi XSD adalah sepotong kode yang baik.


1
Bagaimana saya bisa menambahkan custom header untuk permintaan SOAP Jika saya menambahkan WSDL sebagai referensi layanan web dan juga titik akhir ???
BASEER HAIDER JAFRI

12
Anda menyebutkan untuk melakukan ini, ada referensi tentang BAGAIMANA untuk melakukan ini?
Zapnologica

Jika WSDL tidak ingin header khusus, maka Anda tidak boleh menambahkannya.
StingyJack

1
Pada dasarnya apa yang dibutuhkan untuk mengirim - menerima SABUN? Apakah cukup menggunakan pengikatan yang mendukung SOAP seperti wsHttpBinding dan referensi WSDL? Semuanya sama dengan menggunakan REST (memanggil metode WCF, menerima respons)?
FrenkyB

Saya setuju dengan WSDL, yang pertama jauh lebih kompleks dan tidak perlu. Yang Anda butuhkan adalah masuk ke Referensi Layanan di proyek Anda (Dalam versi Visual Studio yang lebih lama), klik kanan, tambahkan referensi layanan dan masukkan detail yang benar. Objek c # dibuat yang harus dibuat sebagai variabel. Semua fungsionalitas layanan WSDL kemudian diekspos melalui kode
lllllllllllllIllllIll

19

Saya pikir ada cara yang lebih sederhana:

 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);
       }
 }

Ini bekerja seperti juara. Saya menambahkan parameter ke metode CreateSoapEnvelope untuk dapat meneruskan dalam XML string, URL posting, dan URL tindakan untuk membuat metode dapat digunakan kembali dan itu persis apa yang saya cari.
Slippery Pete

jawaban terbaik untuk pendapat saya karena menggunakan HttpClient lebih relevan daripada WebResponse usang.
Akmal Salikhov

15

Saya menulis kelas helper yang lebih umum yang menerima kamus parameter khusus berbasis string, sehingga mereka dapat diatur oleh pemanggil tanpa harus membuat hard-code. Tak perlu dikatakan bahwa Anda hanya boleh menggunakan metode seperti itu ketika Anda ingin (atau perlu) untuk secara manual mengeluarkan layanan web berbasis SOAP: dalam skenario paling umum pendekatan yang disarankan akan menggunakan WSDL Layanan Web bersama-sama dengan Tambah Referensi Layanan Visual Studio fitur sebagai gantinya.

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;
        }
    }
}

Untuk info & detail tambahan mengenai kelas ini Anda juga dapat membaca posting ini di blog saya.


1

Jadi ini adalah kode terakhir saya setelah googling selama 2 hari tentang cara menambahkan namespace dan membuat permintaan sabun bersama dengan amplop SOAP tanpa menambahkan proxy / Referensi Layanan

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

Panggil layanan web SOAP di 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
Apa new UpdatedOutlookServiceReferenceAPI.OutlookServiceSoapClient()?
Chris F Carroll
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.