İstemci SOAP isteği gönderecek ve yanıt alacak


159

Bir web hizmetine SOAP istekleri gönderen (ve sonuçları alan) bir C # istemcisi (Windows hizmeti olarak geliştirilecektir) oluşturmaya çalışılıyor.

Bu sorudan bu kodu gördüm:

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

Güzel görünüyor, nasıl kullanılacağını ve en iyi uygulama olup olmadığını bilen var mı?

Yanıtlar:


224

Normalde aynısını yapmak için başka bir yol kullanırım

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
Bu bir şey, ama ben SOAP istek dizesi dahil, burada her şeyi koydum.
KBBWrite

5
Tamam, sanırım SOAP isteğine koymanız gerekiyor, eğer talep yükü örneği varsa, o zaman böyle bir talep oluşturabilirsiniz. Ne tür bir güvenlik kullandığınızdan emin değilsiniz, WS-Security kullanıyorsanız, SOAP istek Başlığınızla aktarabileceğiniz kullanıcı adı ve parola.
KBBWrite

3
Bunun gibi bir şey düşünüyorum HttpWebRequest webRequest = CreateWebRequest (_url, _action); webRequest.Credentials = yeni NetworkCredential (kullanıcı adı, şifre, etki alanı);
Veri Tabanı

3
@hamish: Bu sadece kavramsal bir kod pasajıdır. Bir üretim kalite kodu olarak düşünmeyin.
KBBWrite

4
Son derece yardımcı oldum ve Telerik Fiddler'ı kullanarak POST'u manuel olarak web servisime yönlendirdim, çünkü belirlediğiniz tüm başlıkları görebiliyordum. Çok teşekkürler.
raddevus

64

Bu basit çözümü burada buldum :

WSDL veya proxy sınıflarını kullanmadan .NET 4.0 C # ile SOAP isteği gönderme ve yanıt alma:

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

Sabun xml istemcisi dize sabun xml kullanarak dışarı oluşturabilir miyiz. C # kodu kullanarak. Gibi: var request = (HttpWebRequest) WebRequest.Create (uri); request.Method = Ortak.Method; Örneğin, parametreleri ile farklı wsdl hizmetlerine birden fazla sabun xml istemcisi oluşturan bir c # yöntemi.
Dvlpr

Aşağıdaki hatayı alıyorum ve kod sonlandırılır: 'sabun' bildirilmemiş bir önektir. Satır 2, konum 18. Bir şey mi kaçırıyorum? Web
hizmetim

İle İşleri webRequest.Headers.Add("SOAPAction", "http://tempuri.org/.....");SoapUI öyle SABUN Eylem edin ve bunu kullanın.
Robert Koch

SOAPAction başlığında iki nokta üst üste kullandığımda hata alıyorum. Yapmam gerek: webRequest.Headers.Add (@ "SOAPAction", "SomeAction");
Geliştirici Webs

PDF'de dosya ve dönüşüm nasıl alınır?
Leandro

20

En iyi uygulama WSDL'ye başvurmak ve bunu bir web hizmeti başvurusu gibi kullanmaktır. Daha kolay ve daha iyi çalışıyor, ancak WSDL'niz yoksa, XSD tanımları iyi bir kod parçasıdır.


1
Web hizmeti başvurusu olarak WSDL ve bitiş noktaları olarak eklersem SOAP isteği için özel üstbilgi nasıl ekleyebilirim?
BASEER HAIDER JAFRI

12
Bunu yapmaktan bahsettiniz, bunu NASIL yapmalısınız?
Zapnologica

WSDL özel bir başlık istemiyorsa, bir başlık eklememelisiniz.
StingyJack

1
Temelde SOAP göndermek - almak için neye ihtiyaç vardır? WsHttpBinding gibi SOAP'ı destekleyen ve WSDL'ye başvuru yapan ciltleme kullanmak yeterli mi? Diğer her şey REST kullanmakla aynıdır (WCF yöntemlerini çağırmak, yanıt almak)?
FrenkyB

WSDL'lerle anlaştım, birincisi çok daha karmaşık ve gereksiz. Tek ihtiyacınız olan projenizde Servis Referansları (Visual Studio'nun eski sürümlerinde), sağ tıklayın, servis referansı ekleyin ve doğru bilgileri girin. Değişken olarak oluşturulması gereken bir c # nesnesi oluşturulur. WSDL hizmetinin tüm işlevleri daha sonra kod aracılığıyla ortaya çıkar
lllllllllllllIllllIll

19

Bence daha basit bir yol var:

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

Bu bir şampiyon gibi çalıştı. Yöntemleri yeniden kullanılabilir hale getirmek için dize XML, posta URL'si ve eylem URL'sini geçebilmek için CreateSoapEnvelope yöntemine parametreler ekledim ve tam olarak aradığım şey buydu.
Kaygan Pete

benim fikrim için en iyi cevap çünkü eski WebResponse yerine daha alakalı HttpClient kullanıyor.
Akmal Salikhov

15

Özel parametrelerin dize tabanlı bir sözlüğünü kabul eden daha genel bir yardımcı sınıf yazdım, böylece arayanlar tarafından sabit kodlamak zorunda kalmadan ayarlanabilirler. Bu yöntemi yalnızca SOAP tabanlı bir web hizmetini el ile vermek istediğinizde (veya ihtiyaç duyduğunuzda) kullanmanız gerektiğini söylemeye gerek yoktur: En yaygın senaryolarda önerilen yaklaşım, Web Hizmeti WSDL'sini Hizmet Ekleme Başvurusu Visual Studio ile birlikte kullanmak olacaktır. yerine.

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

Bu sınıfa ilişkin ek bilgi ve ayrıntılar için bu yayını blogumda da okuyabilirsiniz .


1

Proxy / Hizmet Referansı eklemeden SOAP zarfıyla birlikte bir ad alanı ekleme ve sabun isteği yapma konusunda 2 gün boyunca googling yaptıktan sonra bu son kodum

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

SOAP web hizmetini c # olarak arayın

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
Nedir new UpdatedOutlookServiceReferenceAPI.OutlookServiceSoapClient()?
Chris F Carroll
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.