如何使用 C# 发送/接收 SOAP 请求和响应?

Posted

技术标签:

【中文标题】如何使用 C# 发送/接收 SOAP 请求和响应?【英文标题】:How to send/receive SOAP request and response using C#? 【发布时间】:2011-07-20 18:43:50 【问题描述】:
private static string WebServiceCall(string methodName)        

    WebRequest webRequest = WebRequest.Create("http://localhost/AccountSvc/DataInquiry.asmx");
    HttpWebRequest httpRequest = (HttpWebRequest)webRequest;             
    httpRequest.Method = "POST";             
    httpRequest.ContentType = "text/xml; charset=utf-8";
    httpRequest.Headers.Add("SOAPAction: http://tempuri.org/" + methodName);
    httpRequest.ProtocolVersion = HttpVersion.Version11;
    httpRequest.Credentials = CredentialCache.DefaultCredentials;
    Stream requestStream = httpRequest.GetRequestStream();              
    //Create Stream and Complete Request             
    StreamWriter streamWriter = new StreamWriter(requestStream, Encoding.ASCII);

    StringBuilder soapRequest = new StringBuilder("<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"");
    soapRequest.Append(" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" ");
    soapRequest.Append("xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"><soap:Body>");
    soapRequest.Append("<GetMyName xmlns=\"http://tempuri.org/\"><name>Sam</name></GetMyName>");
    soapRequest.Append("</soap:Body></soap:Envelope>");

    streamWriter.Write(soapRequest.ToString());             
    streamWriter.Close();              
    //Get the Response    
    HttpWebResponse wr = (HttpWebResponse)httpRequest.GetResponse();
    StreamReader srd = new StreamReader(wr.GetResponseStream()); 
    string resulXmlFromWebService = srd.ReadToEnd(); 
    return resulXmlFromWebService;

我尝试了不同的代码来发送/接收肥皂响应,但都以相同的"The remote server returned an error: (500) Internal Server Error." 失败。

我可以使用 SoapUI 访问相同的服务。我也能够调用该方法。我在这个论坛上读到我收到 500 错误的原因可能是错误的标题。我验证了标题,它似乎没问题。如果有人可以提供帮助,我将不胜感激。

以下是示例 SOAP 请求:

POST /AccountSvc/DataInquiry.asmx HTTP/1.1
Host: abc.def.gh.com
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: "http://tempuri.org/GetMyName"

<?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>
    <GetMyName xmlns="http://tempuri.org/">
      <name>string</name>
    </GetMyName>
  </soap:Body>
</soap:Envelope>

我使用上面的示例请求来执行该方法并且它有效。这是我通过的 Soap 请求:

<?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><GetMyName xmlns="http://tempuri.org/"><name>Sam</name></GetMyName></soap:Body></soap:Envelope>

编辑:

我已经更新了 WebServiceCall 中适用于 .asmx 服务的上述代码。但是相同的代码不适用于 WCF 服务。为什么?

【问题讨论】:

更多提示:永远不要使用字符串操作来创建 XML。始终使用 XML API 之一,例如 LINQ to XML 或 XmlWriter。此外,Streams、StreamReader/Writers 和 WebResponse 需要在 using 块中,这样它们就不会在发生异常时泄漏资源。 没有看到你的代码,可能很难说。我会冒险猜测您可能没有指定足够的行为。此链接可能对您有用,因为它描述了 WCF 端点/服务的 SOAP 配置:***.com/questions/186631/… 【参考方案1】:

网址不同。

http://localhost/AccountSvc/DataInquiry.asmx

对比

/acctinqsvc/portfolioinquiry.asmx

首先解决这个问题,如果网络服务器无法解析您尝试 POST 到的 URL,您甚至不会开始处理您的请求所描述的操作。

您应该只需要创建到 ASMX 根 URL 的 WebRequest,即:http://localhost/AccountSvc/DataInquiry.asmx,并在 SOAPAction 标头中指定所需的方法/操作。

SOAPAction 标头值不同。

http://localhost/AccountSvc/DataInquiry.asmx/ + methodName

对比

http://tempuri.org/GetMyName

您应该能够通过转到正确的 ASMX URL 并附加 ?wsdl 来确定正确的 SOAPAction

&lt;wsdl:operation&gt; 标记下方应该有一个 &lt;soap:operation&gt; 标记,与您尝试执行的操作相匹配,这似乎是 GetMyName

请求正文中没有包含您的 SOAP XML 的 XML 声明。

您在 HttpRequest 的 ContentType 中指定 text/xml 并且没有字符集。也许这些默认为us-ascii,但如果您没有指定它们,则无法确定!

SoapUI 创建的 XML 包含一个 XML 声明,该声明指定 utf-8 的编码,它也与提供给 HTTP 请求的 Content-Type 相匹配,即:text/xml; charset=utf-8

希望有帮助!

【讨论】:

抱歉回复晚了。我已经更新了代码,它现在可以工作了。谢谢!您知道为什么相同的代码不适用于 WCF 服务吗?起初它给了我错误:(415)无法处理消息'因为内容类型不是预期的。将其更改为应用程序/soap+xml; charset=utf-8”。然后它说“400 Bad Request”。

以上是关于如何使用 C# 发送/接收 SOAP 请求和响应?的主要内容,如果未能解决你的问题,请参考以下文章

C# WCF的通信模式

空手道-如何使用从响应数组接收的值循环Soap请求

如何通过 HTTP 使用 Java(或 C#)中的摘要身份验证 HTTP 发送 SOAP 请求?

带有 XML 响应和正文的 SOAP 请求 swift 3,Alamofire

如何在 C# 程序中打开 Telnet 会话并以编程方式发送命令和接收响应?

如何在循环中发送多个 SOAP 请求:PHP?