SOAP 요청을 보내고 응답을받는 클라이언트


159

SOAP 요청을 웹 서비스로 보내고 결과를 얻는 C # 클라이언트 (Windows 서비스로 개발 됨)를 만들려고합니다.

질문에서 나는이 코드를 보았다 :

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

멋지게 보이면 누구나 그것을 사용하는 방법을 알고 있으며 그것이 최선의 방법인지 알고 있습니까?

답변:


224

나는 보통 같은 방법으로 다른 방법을 사용합니다

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
그것은 동일하지만 SOAP 요청 문자열을 포함하여 여기에 모든 것을 넣었습니다.
KBBWrite

5
좋아, 요청 페이로드 샘플이 있으면 SOAP 요청에 넣어야한다고 생각합니다. 어떤 종류의 보안을 사용하는지 잘 모르겠습니다. WS-Security를 ​​사용하는 경우 사용자 이름과 비밀번호를 SOAP 요청 헤더와 함께 전달할 수 있습니다.
KBBWrite

3
나는 이런 식으로 생각하고있다 HttpWebRequest webRequest = CreateWebRequest (_url, _action); webRequest.Credentials = 새로운 NetworkCredential (사용자 이름, 비밀번호, 도메인);
데이터베이스

3
@hamish : 이것은 단지 개념적 코드 스 니펫입니다. 프로덕션 품질 코드로 간주하지 마십시오.
KBBWrite

4
Telerik Fiddler를 사용하여 웹 서비스에 대한 POST를 수동으로 수행하는 데 매우 도움이되고 도움이되었습니다. 설정 한 모든 헤더를 볼 수 있었기 때문입니다. 매우 감사합니다.
raddevus

64

이 간단한 해결책을 여기에 얻었 습니다 .

WSDL 또는 프록시 클래스를 사용하지 않고 .NET 4.0 C #에서 SOAP 요청 전송 및 응답 수신 :

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

문자열 soap xml을 사용하지 않고 soap xml 클라이언트를 만들 수 있습니까? C # 코드를 사용합니다. 다음과 같이 : var request = (HttpWebRequest) WebRequest.Create (uri); request.Method = 공통. 방법; 예를 들어, 매개 변수를 사용하여 다른 wsdl 서비스에 대해 하나 이상의 soap xml 클라이언트를 작성하는 하나의 c # 메소드입니다.
Dvlpr

다음과 같은 오류가 발생하고 코드가 종료됩니다. 'soap'은 선언되지 않은 접두사입니다. 2 호선, 위치 18. 뭔가 빠졌습니까? 내 웹 서비스에 대한 SOAP UI 요청은 여기에서 찾을 수 있습니다 : stackoverflow.com/questions/50430398/…
Vesnog

webRequest.Headers.Add("SOAPAction", "http://tempuri.org/.....");SoapUI에있는 SOAP 동작 확인 과 함께 작동하여 사용합니다.
Robert Koch

SOAPAction 헤더에서 콜론을 사용할 때 오류가 발생합니다. webRequest.Headers.Add (@ "SOAPAction", "SomeAction");
개발자 웹 22

PDF로 파일을 받고 변환하는 방법은 무엇입니까?
Leandro

20

가장 좋은 방법은 WSDL을 참조하여 웹 서비스 참조처럼 사용하는 것입니다. 더 쉽고 더 잘 작동하지만 WSDL이없는 경우 XSD 정의는 좋은 코드입니다.


1
웹 서비스 참조 및 엔드 포인트로 WSDL을 추가하는 경우 SOAP 요청에 대한 사용자 정의 헤더를 추가하는 방법은 무엇입니까 ???
BASEER HAIDER JAFRI

12
이 작업을 수행하는 방법에 대한 언급이 있습니까?
Zapnologica

WSDL이 사용자 정의 헤더를 원하지 않으면 추가하지 않아야합니다.
StingyJack

1
기본적으로 SOAP를 받기 위해 필요한 것은 무엇입니까? wsHttpBinding 및 참조 WSDL과 같은 SOAP를 지원하는 바인딩을 사용하는 것으로 충분합니까? 다른 모든 것은 REST (WCF 메소드 호출, 응답 수신)를 사용하는 것과 동일합니까?
FrenkyB

나는 WSDL에 동의했다. 전자는 훨씬 복잡하고 불필요하다. 이전 버전의 Visual Studio에서 프로젝트의 서비스 참조로 이동하여 마우스 오른쪽 단추를 클릭하고 서비스 참조를 추가 한 후 올바른 세부 사항을 입력하십시오. 변수로 작성해야하는 C # 오브젝트가 작성됩니다. WSDL 서비스의 모든 기능은 다음 코드를 통해 노출됩니다
lllllllllllllIllllIll

19

더 간단한 방법이 있다고 생각합니다.

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

이것은 챔피언처럼 작동했습니다. 메서드를 재사용 할 수 있도록 문자열 XML, 게시 URL 및 작업 URL을 전달할 수 있도록 CreateSoapEnvelope 메서드에 매개 변수를 추가했습니다.
Slippery Pete

더 이상 사용되지 않는 WebResponse 대신 관련성이 높은 HttpClient를 사용하기 때문에 내 의견에 가장 적합합니다.
Akmal Salikhov

15

필자는 사용자 정의 매개 변수의 문자열 기반 사전을 허용하는 일반적인 도우미 클래스를 작성하여 호출자가 매개 변수를 지정하지 않고도 설정할 수 있습니다. SOAP 기반 웹 서비스를 수동으로 발행하기를 원하거나 필요로 할 때만 이러한 방법을 사용해야한다는 것은 말할 필요도 없습니다. 대부분의 일반적인 시나리오에서 권장되는 접근 방식은 서비스 추가 Visual Studio 와 함께 웹 서비스 WSDL을 사용하는 것입니다 대신 기능.

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

이 수업에 대한 추가 정보 및 세부 정보 는 내 블로그 에서이 게시물읽을 수도 있습니다 .


1

그래서 이것은 프록시 / 서비스 참조를 추가하지 않고 네임 스페이스를 추가하고 SOAP 봉투와 함께 비누 요청을하는 방법에 대해 2 일 동안 인터넷 검색을 한 마지막 코드입니다.

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

C #에서 SOAP 웹 서비스 호출

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
무엇입니까 new UpdatedOutlookServiceReferenceAPI.OutlookServiceSoapClient()?
크리스 F 캐롤
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.