【问题标题】:Post soap message over http to WCF service error 400通过 http 将肥皂消息发布到 WCF 服务错误 400
【发布时间】:2017-08-20 00:26:22
【问题描述】:

我目前有 2 个应用程序:

  1. WCF 服务
  2. 向我的 WCF 服务触发 HTTP 请求的控制台应用程序

我想向我的 WCF 服务发送 SOAP 消息并解析从 WCF 服务返回的 XML 数据。我可以使用纯 XML 和此端点 URL http://localhost:62147/Service1.svc/Http/ 成功 GET 和 POST,但使用 SOAP 则无法正常工作。发送请求时出现以下错误。

例外

An unhandled exception of type 'System.Net.WebException' occurred in System.dll

Additional information: The remote server returned an error: (400) Bad Request.

WCF 服务 web.config

<?xml version="1.0"?>
<configuration>
    <system.web>
        <compilation debug="true" targetFramework="4.5" />
        <httpRuntime targetFramework="4.5"/>
    </system.web>
    <system.serviceModel>
        <behaviors>
            <serviceBehaviors>
                <behavior>
                    <!-- To avoid disclosing metadata information, set the values below to false before deployment -->
                    <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
                    <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
                    <serviceDebug includeExceptionDetailInFaults="false"/>
                </behavior>
            </serviceBehaviors>
        </behaviors>
        <services>
            <service name="WcfService1.Service1">
                <endpoint address="Soap" binding="basicHttpBinding" contract="WcfService1.IService1" />
                <endpoint address="Http" kind="webHttpEndpoint" contract="WcfService1.IService1" />
                <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
            </service>
        </services>
        <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
    </system.serviceModel>
    <system.webServer>
        <modules runAllManagedModulesForAllRequests="true"/>
        <httpErrors errorMode="Detailed"/>
    </system.webServer>
</configuration>

WCF IService1

[ServiceContract]
public interface IService1
{
    [OperationContract]
    [WebInvoke]
    string GetData(string channel);
}

控制台应用

private static string HttpPost(string _postData)
{
    using (WebClient webClient = new WebClient())
    {
        webClient.BaseAddress = "http://localhost:62147/Service1.svc/Soap/";
        webClient.Headers.Add("Content-Type", "text/xml; charset=utf-8");
        webClient.Headers.Add("SOAPAction", "http://tempuri.org/IService1/GetData");

        byte[] response = webClient.UploadData("GetData", Encoding.UTF8.GetBytes(_postData));

        return Encoding.UTF8.GetString(response);
    }
}

肥皂消息 我从 WCF 测试客户端复制了这个。

const string soapMsg = @"
    <s:Envelope xmlns:s=""http://schemas.xmlsoap.org/soap/envelope/"">
        <s:Header>
            <Action s:mustUnderstand=""1"" xmlns=""http://schemas.microsoft.com/ws/2005/05/addressing/none"">http://tempuri.org/IService1/GetData</Action>
        </s:Header>
        <s:Body>
            <GetData xmlns=""http://tempuri.org/"">
                <channel>1</channel>
            </GetData>
        </s:Body>
    </s:Envelope>";

【问题讨论】:

  • 尝试&lt;endpoint address="Soap" binding="wsHttpBinding" contract="WcfService1.IService1" /&gt; 而不是&lt;endpoint address="Soap" binding="basicHttpBinding" contract="WcfService1.IService1" /&gt;。 BasicHttpBinding 是旧绑定,如果可用,请使用 wsHttpBinding
  • @tomassino 同样的错误。

标签: c# wcf soap


【解决方案1】:

尝试在 soapMsg 中添加编码声明。

const string soapMsg = @"
    <?xml version=""1.0"" encoding=""UTF-8""?>
    <s:Envelope xmlns:s=""http://schemas.xmlsoap.org/soap/envelope/"">
        <s:Header>
            <Action s:mustUnderstand=""1"" xmlns=""http://schemas.microsoft.com/ws/2005/05/addressing/none"">http://tempuri.org/IService1/GetData</Action>
        </s:Header>
        <s:Body>
            <GetData xmlns=""http://tempuri.org/"">
                <channel>1</channel>
            </GetData>
        </s:Body>
    </s:Envelope>";

您需要向您的 SOAP 服务发出 GET 请求,您已经使用 WebMethod 属性修饰了 GetData 方法,其默认 HTTP 方法是 GET。

尝试使用DownloadString 方法而不是UploadData,因为UploadData 默认使用POST 方法发出请求。但是,您需要将属性WebInvoke更改为WebGet

【讨论】:

  • 感谢您的回复,我刚刚尝试过,我得到了同样的错误。
【解决方案2】:

考虑使用 HttpWebRequest 和 WebResponse 代替 WebClient

    public static void PerformSOAPRequest(string xml_message)
    {
        HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(@"http://localhost:62147/Service1.svc/Soap/");
        webRequest.Headers.Add(@"SOAPAction", "http://tempuri.org/IService1/GetData");
        webRequest.ContentType = "text/xml;charset=\"utf-8\"";
        webRequest.Accept = "text/xml";
        webRequest.Method = "POST";

        XmlDocument soapEnvelopeXml = new XmlDocument();
        soapEnvelopeXml.LoadXml(xml_message);

        using (Stream stream = webRequest.GetRequestStream())
        {
            soapEnvelopeXml.Save(stream);
        }
        using (WebResponse response = webRequest.GetResponse())
        {
            using (StreamReader rd = new StreamReader(response.GetResponseStream()))
            {
                string soapResult = rd.ReadToEnd();
                Console.WriteLine(soapResult);
            }
        }
    }

【讨论】:

    【解决方案3】:

    我认为问题在于如何将 XML 数据附加到请求中。这是我为 WebGet 提供的工作示例。这也适用于 WebInvoke 方法,但当然,只需要使用预期的参数修改皂体

    控制台应用

    private static void TestGet()
    {
        Console.WriteLine("[TestGet]\n");
    
        const string soapMsg = @"<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>
                    <TestGet xmlns=""http://tempuri.org/"" SOAP-ENV:encodingStyle=""http://schemas.xmlsoap.org/soap/encoding/"" />
                </SOAP-ENV:Body>
            </SOAP-ENV:Envelope>";
    
        PerformSOAPRequest(URL, "TestGet", soapMsg);
    }
    
    public static void PerformSOAPRequest(string _url, string _method, string xml_message)
    {
        HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(_url);
        webRequest.Accept = "text/xml";
        webRequest.ContentType = "text/xml;charset=\"utf-8\"";
        webRequest.Headers.Add(@"SOAPAction", string.Format("http://tempuri.org/IService1/{0}", _method));
        webRequest.Method = "POST";
    
        byte[] bytes = Encoding.UTF8.GetBytes(xml_message);
    
        webRequest.ContentLength = bytes.Length;
    
        using (Stream putStream = webRequest.GetRequestStream())
        {
            putStream.Write(bytes, 0, bytes.Length);
        }
    
        using (WebResponse response = webRequest.GetResponse())
        using (StreamReader rd = new StreamReader(response.GetResponseStream()))
        {
            string soapResult = rd.ReadToEnd();
    
            Console.WriteLine(soapResult);
        }
    }
    

    WCF 中的 IService1

    [ServiceContract]
    public interface IService1
    {
        [OperationContract]
        [WebGet(BodyStyle = WebMessageBodyStyle.Wrapped,
            RequestFormat = WebMessageFormat.Xml,
            ResponseFormat = WebMessageFormat.Xml,
            UriTemplate = "/TestGet")]
        string TestGet();
    }
    

    【讨论】:

      【解决方案4】:

      您需要从 SOAP 信封中删除行:

      <s:Header>
         <Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://tempuri.org/IService1/GetData</Action>
      </s:Header>
      

      它对我有用...

      【讨论】:

        猜你喜欢
        • 2011-06-29
        • 2012-07-17
        • 2016-09-13
        • 1970-01-01
        • 2018-04-12
        • 1970-01-01
        • 1970-01-01
        • 2020-06-11
        • 2011-06-04
        相关资源
        最近更新 更多