Khách hàng gửi yêu cầu SOAP và nhận phản hồi


159

Cố gắng tạo ứng dụng khách C # (sẽ được phát triển dưới dạng dịch vụ Windows) gửi yêu cầu SOAP đến dịch vụ web (và nhận kết quả).

Từ câu hỏi này, tôi thấy mã này:

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

Trông thật tuyệt, có ai biết cách sử dụng nó và nếu đó là cách thực hành tốt nhất?

Câu trả lời:


224

Tôi thường sử dụng một cách khác để làm tương tự

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
Đó là lấy mẫu, nhưng tôi đã đặt mọi thứ ở đây, bao gồm cả chuỗi yêu cầu SOAP.
KBBWrite

5
ok, tôi nghĩ rằng bạn phải đặt nó trong yêu cầu SOAP, nếu bạn có một mẫu tải trọng yêu cầu, thì bạn có thể xây dựng một yêu cầu như thế. Không chắc chắn bạn sử dụng loại bảo mật nào, Nếu bạn đang sử dụng WS-Security thì tên người dùng và mật khẩu bạn có thể chuyển với Tiêu đề yêu cầu SOAP của bạn.
KBBWrite

3
Tôi đang suy nghĩ về một cái gì đó giống như thế này httpWebRequest webRequest = CreateWebRequest (_url, _action); webRequest.Credentials = new NetworkCredential (tên người dùng, mật khẩu, tên miền);
Cơ sở dữ liệu

3
@hamish: đây chỉ là một đoạn mã khái niệm. Đừng coi đó là một mã chất lượng sản xuất.
KBBWrite

4
Vô cùng hữu ích và giúp tôi làm việc thông qua việc sử dụng Telerik Fiddler để POST thủ công cho dịch vụ web của mình, bởi vì tôi có thể thấy tất cả các tiêu đề bạn đặt. Cảm ơn rất nhiều.
raddevus

64

Tôi có giải pháp đơn giản này ở đây :

Gửi yêu cầu SOAP và nhận phản hồi trong .NET 4.0 C # mà không cần sử dụng các lớp WSDL hoặc 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();
        }
    }

Chúng tôi có thể tạo ra khách hàng xml xà phòng mà không cần sử dụng chuỗi xà phòng xml. Với việc sử dụng mã c #. Giống như: var request = (HttpWebRequest) WebRequest.Create (uri); request.Method = Common.Method; Ví dụ: một phương thức c # tạo nhiều hơn một máy khách xml xà phòng cho các dịch vụ wsdl khác nhau với các tham số.
Dvlpr

Tôi nhận được lỗi sau và mã chấm dứt: 'xà phòng' là tiền tố chưa được khai báo. Dòng 2, vị trí 18. Tôi có thiếu thứ gì không? Yêu cầu giao diện người dùng SOAP cho dịch vụ web của tôi có thể được tìm thấy ở đây: stackoverflow.com/questions/50430398/iêu
Vesnog

Hoạt động với webRequest.Headers.Add("SOAPAction", "http://tempuri.org/.....");Kiểm tra hành động SOAP trong SoapUI và sử dụng nó.
Robert Koch

Tôi gặp lỗi khi tôi sử dụng dấu hai chấm trong tiêu đề SOAPAction. Tôi phải làm: webRequest.Headers.Add (@ "SOAPAction", "someAction");
Nhà phát triển Web

Làm thế nào nhận được tập tin và chuyển đổi trong PDF?
Leandro

20

Cách thực hành tốt nhất là tham chiếu WSDL và sử dụng nó như tham chiếu dịch vụ web. Nó dễ dàng hơn và hoạt động tốt hơn, nhưng nếu bạn không có WSDL, các định nghĩa XSD là một đoạn mã tốt.


1
Làm cách nào tôi có thể thêm tiêu đề tùy chỉnh cho yêu cầu SOAP Nếu tôi thêm WSDL làm tham chiếu dịch vụ web và cũng là điểm kết thúc ???
BASEER HAIDER JAFRI

12
Bạn đề cập để làm điều này, bất kỳ tài liệu tham khảo về CÁCH để làm điều này?
Zapnologica

Nếu WSDL không muốn một tiêu đề tùy chỉnh, thì bạn không nên thêm một tiêu đề.
StingyJack

1
Về cơ bản những gì cần thiết để gửi - nhận SOAP? Có đủ để sử dụng liên kết hỗ trợ SOAP như wsHttpBinding và WSDL tham chiếu không? Mọi thứ khác giống như sử dụng REST (gọi phương thức WCF, nhận phản hồi)?
FrenkyB

Tôi đã đồng ý với WSDL, trước đây là cách phức tạp hơn và không cần thiết. Tất cả những gì bạn cần là truy cập vào Tài liệu tham khảo dịch vụ trong dự án của bạn (Trong các phiên bản cũ hơn của Visual Studio), nhấp chuột phải, thêm tham chiếu dịch vụ và nhập chi tiết chính xác. Một đối tượng c # được tạo phải được tạo như một biến. Tất cả chức năng của dịch vụ WSDL sau đó được bộc lộ thông qua mã
lllllllllllIllllIll

19

Tôi nghĩ có một cách đơn giản hơn:

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

Điều này làm việc như một nhà vô địch. Tôi đã thêm các tham số cho phương thức CreateSoapEnvel để có thể truyền vào chuỗi XML, URL bài đăng và URL hành động để làm cho các phương thức có thể sử dụng lại và đó chính xác là những gì tôi đang tìm kiếm.
Slippery Pete

Câu trả lời tốt nhất cho ý kiến ​​của tôi bởi vì nó sử dụng httpClient phù hợp hơn thay vì WebResponse lỗi thời.
Akmal Salikhov

15

Tôi đã viết một lớp trình trợ giúp tổng quát hơn, chấp nhận một từ điển dựa trên chuỗi các tham số tùy chỉnh, để người gọi có thể đặt chúng mà không cần phải mã hóa chúng. Không cần phải nói rằng bạn chỉ nên sử dụng phương pháp đó khi bạn muốn (hoặc cần) phát hành dịch vụ web dựa trên SOAP theo cách thủ công: trong hầu hết các trường hợp phổ biến, cách tiếp cận được đề xuất sẽ sử dụng WSDL của Dịch vụ Web cùng với Thêm Visual Reference Reference Studio tính năng thay thế.

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

Để biết thêm thông tin và chi tiết về lớp học này, bạn cũng có thể đọc bài đăng này trên blog của tôi.


1

Vì vậy, đây là mã cuối cùng của tôi sau khi googling trong 2 ngày về cách thêm không gian tên và thực hiện yêu cầu xà phòng cùng với phong bì SOAP mà không cần thêm proxy / Tham chiếu dịch vụ

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

Gọi dịch vụ web SOAP trong 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
new UpdatedOutlookServiceReferenceAPI.OutlookServiceSoapClient()
Chris F Carroll
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.