服务参数始终为null,但我可以在跟踪中看到它

时间:2011-07-11 14:59:42

标签: wcf soap

我在实施基于第三方wsdl的服务时遇到了麻烦。第三方调用我的服务,我可以看到跟踪中的数据,但我的服务参数在反序列化后仍然保持为null。

从跟踪中可以看出,alertXML节点包含一个XML文档作为字符串。在服务代码中,此alertXML字符串始终为null。我需要做一些特殊的处理才能处理这个XML-as-a-string场景?

除此之外,我有什么方法可以抓住整个信封,以便我可以解析这个问题吗?

由于

<E2ETraceEvent xmlns="http://schemas.microsoft.com/2004/06/E2ETraceEvent">
<System xmlns="http://schemas.microsoft.com/2004/06/windows/eventlog/system">
    <EventID>0</EventID>
    <Type>3</Type>
    <SubType Name="Information">0</SubType>
    <Level>8</Level>
    <TimeCreated SystemTime="2011-07-08T17:46:14.7804786Z" />
    <Source Name="System.ServiceModel.MessageLogging" />
    <Correlation ActivityID="{54a3d088-5393-45a7-ae97-0bcd636f1750}" />
    <Execution ProcessName="w3wp" ProcessID="3468" ThreadID="17" />
    <Channel/>
    <Computer>COMPUTER</Computer>
</System>
<ApplicationData>
    <TraceData>
        <DataItem>
            <MessageLogTraceRecord Time="2011-07-08T13:46:14.7804786-04:00" Source="TransportReceive" Type="System.ServiceModel.Channels.BufferedMessage" xmlns="http://schemas.microsoft.com/2004/06/ServiceModel/Management/MessageTrace">
                <HttpRequest>
                    <Method>POST</Method>
                    <QueryString></QueryString>
                    <WebHeaders>
                        <Content-Length>1807</Content-Length>
                        <Content-Type>text/xml; charset=utf-8</Content-Type>
                        <Expect>100-continue</Expect>
                        <Host>host</Host>
                        <User-Agent>Mozilla/4.0 (compatible; MSIE 6.0; MS Web Services Client Protocol 2.0.50727.3623)</User-Agent>
                        <SOAPAction>"http://www.xyz.com/wsdl/ProcessXML"</SOAPAction>
                    </WebHeaders>
                </HttpRequest>
                <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>
                        <ProcessXML xmlns="http://www.xyz.com/wsdl/">
                            <alertXml>&lt;?xml version="1.0" encoding="UTF-8"?&gt;&lt;XMLOutgoing&gt;MORE XML STRING&lt;/XMLOutgoing&gt;</alertXml>
                        </ProcessXML>
                    </soap:Body>
                </soap:Envelope>
            </MessageLogTraceRecord>
        </DataItem>
    </TraceData>
</ApplicationData>

修改 wsdl是:

    <?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
                  xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/"
                  xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
                  xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
                  xmlns:tns="http://www.xyz.com/wsdl/"
                  xmlns:s="http://www.w3.org/2001/XMLSchema"
                  xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"
                  xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
                  targetNamespace="http://www.xyz.com/wsdl/"
                  xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
  <wsdl:types>
    <s:schema elementFormDefault="qualified" targetNamespace="http://www.xyz.com/wsdl/">
      <s:element name="ProcessXML">
        <s:complexType>
          <s:sequence>
            <s:element minOccurs="0" maxOccurs="1" name="alertXml" type="s:string"/>
          </s:sequence>
        </s:complexType>
      </s:element>
      <s:element name="ProcessXMLResponse">
        <s:complexType>
          <s:sequence>
            <s:element minOccurs="0" maxOccurs="1" name="ProcessXMLResult">
              <s:complexType mixed="true">
                <s:sequence>
                  <s:any/>
                </s:sequence>
              </s:complexType>
            </s:element>
          </s:sequence>
        </s:complexType>
      </s:element>
    </s:schema>
  </wsdl:types>
  <wsdl:message name="ProcessXMLSoapIn">
    <wsdl:part name="parameters" element="tns:ProcessXML"/>
  </wsdl:message>
  <wsdl:message name="ProcessXMLSoapOut">
    <wsdl:part name="parameters" element="tns:ProcessXMLResponse"/>
  </wsdl:message>
  <wsdl:message name="ProcessXMLHttpGetIn">
    <wsdl:part name="alertXml" type="s:string"/>
  </wsdl:message>
  <wsdl:message name="ProcessXMLHttpGetOut">
    <wsdl:part name="Body"/>
  </wsdl:message>
  <wsdl:message name="ProcessXMLHttpPostIn">
    <wsdl:part name="alertXml" type="s:string"/>
  </wsdl:message>
  <wsdl:message name="ProcessXMLHttpPostOut">
    <wsdl:part name="Body"/>
  </wsdl:message>
  <wsdl:portType name="GenericServiceSoap">
    <wsdl:operation name="ProcessXML">
      <wsdl:input message="tns:ProcessXMLSoapIn"/>
      <wsdl:output message="tns:ProcessXMLSoapOut"/>
    </wsdl:operation>
  </wsdl:portType>
  <wsdl:portType name="GenericServiceHttpGet">
    <wsdl:operation name="ProcessXML">
      <wsdl:input message="tns:ProcessXMLHttpGetIn"/>
      <wsdl:output message="tns:ProcessXMLHttpGetOut"/>
    </wsdl:operation>
  </wsdl:portType>
  <wsdl:portType name="GenericServiceHttpPost">
    <wsdl:operation name="ProcessXML">
      <wsdl:input message="tns:ProcessXMLHttpPostIn"/>
      <wsdl:output message="tns:ProcessXMLHttpPostOut"/>
    </wsdl:operation>
  </wsdl:portType>
  <wsdl:binding name="GenericServiceSoap" type="tns:GenericServiceSoap">
    <soap:binding transport="http://schemas.xmlsoap.org/soap/http"/>
    <wsdl:operation name="ProcessXML">
      <soap:operation soapAction="http://www.xyz.com/wsdl/ProcessXML" style="document"/>
      <wsdl:input>
        <soap:body use="literal"/>
      </wsdl:input>
      <wsdl:output>
        <soap:body use="literal"/>
      </wsdl:output>
    </wsdl:operation>
  </wsdl:binding>
  <wsdl:binding name="GenericServiceSoap12" type="tns:GenericServiceSoap">
    <soap12:binding transport="http://schemas.xmlsoap.org/soap/http"/>
    <wsdl:operation name="ProcessXML">
      <soap12:operation soapAction="http://www.xyz.com/wsdl/ProcessXML" style="document"/>
      <wsdl:input>
        <soap12:body use="literal"/>
      </wsdl:input>
      <wsdl:output>
        <soap12:body use="literal"/>
      </wsdl:output>
    </wsdl:operation>
  </wsdl:binding>
  <wsdl:binding name="GenericServiceHttpGet" type="tns:GenericServiceHttpGet">
    <http:binding verb="GET"/>
    <wsdl:operation name="ProcessXML">
      <http:operation location="/ProcessXML"/>
      <wsdl:input>
        <http:urlEncoded/>
      </wsdl:input>
      <wsdl:output>
        <mime:content part="Body" type="text/xml"/>
      </wsdl:output>
    </wsdl:operation>
  </wsdl:binding>
  <wsdl:binding name="GenericServiceHttpPost" type="tns:GenericServiceHttpPost">
    <http:binding verb="POST"/>
    <wsdl:operation name="ProcessXML">
      <http:operation location="/ProcessXML"/>
      <wsdl:input>
        <mime:content type="application/x-www-form-urlencoded"/>
      </wsdl:input>
      <wsdl:output>
        <mime:content part="Body" type="text/xml"/>
      </wsdl:output>
    </wsdl:operation>
  </wsdl:binding>
  <wsdl:service name="GenericService">
  </wsdl:service>
</wsdl:definitions>

服务代码的骨架是:

Public Function ProcessXML(request As ProcessXMLRequest) As ProcessXMLResponse Implements GenericServiceSoap.ProcessXML
    'request.Body is a non-null object but request.Body.alertXml is null
End Function

1 个答案:

答案 0 :(得分:1)

要在WCF中的DataContract中将XML作为参数或属性发送,您需要将XmlElement用于参数或属性的.NET类型。根据问题中的WSDL,alertXml将被WCF序列化为字符串而不是XML。以下是XML操作参数的WSDL:

<xs:element name="alertXml" nillable="true" minOccurs="0">
    <xs:complexType>
        <xs:sequence>
            <xs:any minOccurs="0" processContents="lax"/>
        </xs:sequence>
    </xs:complexType>
</xs:element>

要查看所有WSDL应该是什么样子,请实现这样的服务:

[ServiceContract]
public interface IService1
{

    [OperationContract]
    string ProcessXml(XmlElement alertXml);

    [OperationContract]
    string ProcessSomeXml(ProcessXMLRequest xmlRequest);
}

[DataContract]
public class ProcessXMLRequest
{
    public XmlElement someXml { get; set; }
}

//Service implementation
public class Service1 : IService1
{
    public string ProcessXml(XmlElement alertXml)
    {
        XmlNode xmlToProcess = GetXmlToProcess(alertXml);

        return string.Format("You entered: {0}", xmlToProcess.InnerText);
    }

    public string ProcessSomeXml(ProcessXMLRequest xmlRequest)
    {
        XmlNode xmlToProcess = GetXmlToProcess(xmlRequest.someXml);

        return string.Format("You entered some: {0}", xmlToProcess.InnerText);
    }

    private XmlNode GetXmlToProcess(XmlElement alertXml)
    {
        var xmlToProcess = alertXml as XmlNode;

        if (xmlToProcess == null)
        {
            var x = new XmlDocument();
            x.LoadXml("<root>XML was null</root>");
            xmlToProcess = x;
        }
        return xmlToProcess;
    }
}