【问题标题】:How do I send SOAP Request to WCF Service?如何向 WCF 服务发送 SOAP 请求?
【发布时间】:2020-07-15 23:50:27
【问题描述】:

谁能给我举个例子,如何将SOAP 请求发布到WCF 服务并返回 SOAP 响应?基本上,Travel 客户端发送带有搜索参数的 SOAP 请求,WCF 服务检查数据库,然后发送适当的假期。

我一直收到这个错误,我使用的方法是:“远程服务器返回错误:(400) 错误请求”

【问题讨论】:

    标签: wcf


    【解决方案1】:

    你得到的错误是因为服务器不理解 HTTP 请求。 可能是您配置的绑定或客户端级别的服务代理不正确。

    或者您定义的服务需要 HTTP GET 而不是 HTTP POST。有时,添加服务引用可能不会为某些 [WebGet] 属性操作生成正确的 HTTP 谓词。客户端操作可能需要手动添加[WebGet]。

    【讨论】:

      【解决方案2】:

      要么查看SoapUI,要么找到隐藏在Visual Studio 文件夹深处的WcfTestClient (C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE)。

      两者都可以连接到 WCF 服务并发送/接收 SOAP 消息。

      或者创建你自己的小客户端,使用svcutil.exe

      svcutil.exe  (service URL)
      

      将为您创建一个小 *.cs 文件和一个 *.config 文件,然后您可以使用它们来调用服务。

      马克

      【讨论】:

        【解决方案3】:

        您没有详细说明您在服务方面的进展情况,因此很难说。

        如果这是对服务的第一次命中,则如果 WCF 未在 IIS 中正确注册,则可能会发生此错误。具体来说,.svc 扩展名需要映射到 ASP.NET ISAPI 模块。

        【讨论】:

          【解决方案4】:

          感谢您抽出时间回答这个问题。 该服务工作正常,如果客户端创建对我的 WCF 服务的引用并进行方法调用,则会发送适当的响应。

          我忘了补充,我的客户端正在向我的 WCF 服务发送一个 HTTP Post 请求。 然后创建适当的响应并将其返回给客户端。

          我可以读取 HTTP 请求,但是当我尝试访问 HTTP 响应时,我收到错误 -“远程服务器返回错误:(400) 错误请求”强>

          当代码到达这一行时发生错误:

                  // Get the response. 
                  HttpWebResponse response = request.GetResponse() as HttpWebResponse;
          

          见下面的代码:

           private void CreateMessage()
              {
                  // Create a request using a URL that can receive a post. 
                  WebRequest request = WebRequest.Create("http://www.XXXX.com/Feeds");
                  string postData = "<airport>Heathrow</airport>"; 
          

          // 用户函数 request.Method = "POST";

                  byte[] byteArray = Encoding.UTF8.GetBytes(postData);
                  request.ContentType = "application/soap+xml; charset=utf-8";
                  request.ContentLength = byteArray.Length;
          
                  Stream dataStream = request.GetRequestStream();
                  dataStream.Write(byteArray, 0, byteArray.Length);
                  dataStream.Close();
          
                  // Get the response. 
                  HttpWebResponse response = request.GetResponse() as HttpWebResponse;
          
                  // Display the status. 
                  HttpContext.Current.Response.Write(((HttpWebResponse)response).StatusDescription);
          
                  // Get the stream containing content returned by the server. 
                  dataStream = response.GetResponseStream();
          
                  // Open the stream using a StreamReader for easy access. 
                  StreamReader reader = new StreamReader(dataStream);
          
                  // Read the content. 
                  string responseFromServer = reader.ReadToEnd();
          
                  // Display the content. 
                  HttpContext.Current.Response.Write(responseFromServer);
          
                  // Clean up the streams. 
                  reader.Close();
                  dataStream.Close();
                  response.Close(); 
          
              }
          

          问候

          小乔

          【讨论】:

            【解决方案5】:

            注意

            从其他 .NET 应用程序访问 WCF 服务的推荐方法是使用“连接的服务”参考。下面我将描述如何以更加手动(不建议用于生产代码)的方式创建和发送 SOAP 请求。

            总之

            你需要:

            • Content-Type: text/xml; charset=utf-8标头
            • SOAPAction: http://tempuri.org/YourServiceClass/YourAction标头
            • 请求包装在 SOAP 信封中的内容。

            加长版(示例)

            让我们以 WCF 服务应用程序脚手架为例。

            [ServiceContract]
            public interface IService1
            {
                [OperationContract]
                string GetData(int value);
            }
            
            public class Service1 : IService1
            {
                public string GetData(int value)
                {
                    return string.Format("You entered: {0}", value);
                }
            }
            

            使用 Wireshark,我发现默认方式(连接服务引用)的请求包含 Content-Type: text/xml; charset=utf-8SOAPAction: http://tempuri.org/IService1/GetData 标头和以下 SOAP 信封:

            <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
                <s:Body>
                    <GetData xmlns="http://tempuri.org/"> <!-- Action name -->
                        <value>123</value> <!-- Parameters -->
                    </GetData>
                </s:Body>
            </s:Envelope>
            

            使用 Insomnia,我测试了它是我们使请求成功通过所需要的,所以现在只需要将它移植到 C#:

            // netcoreapp3.1
            static async Task<string> SendHttpRequest(string serviceUrl, int value)
            {
                // Example params:
                //  serviceUrl: "http://localhost:53045/Service1.svc"
                //  value: 123
                using var client = new HttpClient();
            
                var message = new HttpRequestMessage(HttpMethod.Post, serviceUrl);
                message.Headers.Add("SOAPAction", "http://tempuri.org/IService1/GetData"); // url might need to be wrapped in ""
                var requestContent = @$"
            <s:Envelope xmlns:s=""http://schemas.xmlsoap.org/soap/envelope/"">
            <s:Body>
                <GetData xmlns=""http://tempuri.org/"">
                    <value>{value}</value>
                </GetData>
            </s:Body>
            </s:Envelope>
            ";
            
                message.Content = new StringContent(requestContent, System.Text.Encoding.UTF8, "text/xml");
            
                var response = await client.SendAsync(message);
            
                if (!response.IsSuccessStatusCode)
                    throw new Exception("Request failed.");
            
                var responseContent = await response.Content.ReadAsStringAsync();
            /*
            <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
            <s:Body>
                <GetDataResponse xmlns="http://tempuri.org/">
                    <GetDataResult>You entered: {value}</GetDataResult>
                </GetDataResponse>
            </s:Body>
            </s:Envelope>
            */
                // Just a really ugly regex
                var regex = new Regex(@"(<GetDataResult>)(.*)(<\/GetDataResult>)");
                var responseValue = regex.Match(responseContent).Groups[2].Value;
            
                return responseValue;
            }
            

            你可以。如果愿意,请使用 WebClient 而不是 HttpClient

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多