【问题标题】:WCF XML Serialization Issue from Soap Request来自 Soap 请求的 WCF XML 序列化问题
【发布时间】:2016-12-21 09:33:22
【问题描述】:

输入 Xml

  <ws:processAcord xmlns:ws="http://ws.plus.predictivelogic.com/">
    <arg0>CrlUser</arg0>
    <arg1>CrlPass</arg1>
    <arg2>Life Scope</arg2>
    <arg3 />
  </ws:processAcord>

对象类

[XmlRoot(ElementName = "processAcord", Namespace = "http://ws.plus.predictivelogic.com/")]
    public class Input
    {
        //[DataMember]
        [XmlElement(ElementName = "arg0")]
        public string Arg0 { get; set; }
        //[DataMember]
        [XmlElement(ElementName = "arg1")]
        public string Arg1 { get; set; }
        //[DataMember]
        [XmlElement(ElementName = "arg2")]
        public string Arg2 { get; set; }
        //[DataMember]
        [XmlElement(ElementName = "arg3")]
        public string Arg3 { get; set; }
        //[DataMember]
        [XmlAttribute(AttributeName = "ws", Namespace = "http://www.w3.org/2000/xmlns/")]
        public string Ws { get; set; }
    }

服务定义

public UnderWritingOutput Get(Input inputXml)
{
//do stuff
}

我正在尝试从 SOAPUI 调用我的服务,但这会导致序列化问题。调试时,我没有在 Service 中获取任何数据。

我的代码肯定有一些属性声明问题,例如[DataContract] 或任何其他xml 属性。

更新 1:

我已经发布了服务细节,这里是绑定..

<system.serviceModel>
<services>
  <service name="ServiceApplication.UnderWritingService" behaviorConfiguration="debug">
    <endpoint address="GetUnderWriting" binding="basicHttpBinding" contract="ServiceApplication.IUnderWritingService"></endpoint>
    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"></endpoint>
    <host>
      <baseAddresses>
        <add baseAddress="http://localhost:60418/"/>
      </baseAddresses>
    </host>
  </service>
</services>
<behaviors>

  <serviceBehaviors>
    <behavior name="debug">
      <serviceDebug includeExceptionDetailInFaults="true" />
      <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
    </behavior>
    <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>
<protocolMapping>
  <add binding="basicHttpsBinding" scheme="https" />
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />

当我打开soapUI请求时,它会向我显示输入xml

    <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tem="http://tempuri.org/" xmlns:ser="http://schemas.datacontract.org/2004/07/ServiceApplication">
   <soapenv:Header/>
   <soapenv:Body>
      <tem:Get>
         <!--Optional:-->
         <tem:inputXml>
            <!--Optional:-->
            <ser:Arg0>?</ser:Arg0>
            <!--Optional:-->
            <ser:Arg1>?</ser:Arg1>
            <!--Optional:-->
            <ser:Arg2>?</ser:Arg2>
            <!--Optional:-->
            <ser:Arg3>?</ser:Arg3>
            <!--Optional:-->
            <ser:Ws>?</ser:Ws>
         </tem:inputXml>
      </tem:Get>
   </soapenv:Body>
</soapenv:Envelope>

IUnderWritingService

[ServiceContract]
    public interface IUnderWritingService
    {
        [OperationContract]
        UnderWritingOutput Get(UnderWritingInput inputXml);

    }

【问题讨论】:

  • SoapUI 认为您的操作和消息在命名空间 xmlns:tem="http://tempuri.org/" 中,而您的第一个 xml 显示不同的命名空间。你想要发生的事情是什么?
  • 我在这里发布的第一个 XML,应该是我的服务的输入。
  • 但是您确实希望它是一个 SOAP 网络服务,对吧?不是带有简单帖子的 REST 服务?

标签: c# xml wcf soap


【解决方案1】:

DataContract 序列化程序无法序列化您的 XML 结构,因为它不喜欢元素位于不同命名空间中的事实。如果需要该 XML 格式,请通过添加属性 [XmlSerializerFormat] 来告诉 WCF 堆栈使用 XmlSerializer 代替。

[XmlRoot(ElementName = "processAcord", Namespace = "http://ws.plus.predictivelogic.com/")]
[XmlSerializerFormat]  // tell WCF to not to use the DataContractSerializer
public class Input
{
    [XmlElement(ElementName = "arg0", Namespace = "")]
    public string Arg0 { get; set; }
    [XmlElement(ElementName = "arg1", Namespace = "")]
    public string Arg1 { get; set; }
    [XmlElement(ElementName = "arg2", Namespace = "")]
    public string Arg2 { get; set; }
    [XmlElement(ElementName = "arg3", Namespace = "")]
    public string Arg3 { get; set; }
    [XmlAttribute(AttributeName = "ws", Namespace = "http://www.w3.org/2000/xmlns/")]
    public string Ws { get; set; }
}

以下 LinqPad 测试台证明这确实可以渲染结果:

var xml = @"<ws:processAcord xmlns:ws=""http://ws.plus.predictivelogic.com/"">
<arg0>CrlUser</arg0>
<arg1>CrlPass</arg1>
<arg2>Life Scope</arg2>
<arg3 />
</ws:processAcord>";

var xs = new XmlSerializer(typeof(Input));
var rdr = XmlReader.Create(new StringReader(xml));
var obj = (Input) xs.Deserialize(rdr);
obj.Dump();

执行时,结果如下:

如果您更愿意使用 DataContractSerializer,则必须更改您的 xml,以便 arg0、arg1、arg2 和 arg3 元素也在 ws 命名空间中,如下所示:&lt;ws:arg0&gt;CrlUser&lt;/ws:arg0&gt;

接下来是确保您的服务确实理解该有效负载。您的 ServiceContract 应该包含命名空间:

[ServiceContract(Namespace="http://ws.plus.predictivelogic.com/"]
public interface IUnderWritingService
{
    [OperationContract]
    UnderWritingOutput Get(UnderWritingInput inputXml);

}

您没有明确说明这一点,但请注意数据合同可能是 wrapped

【讨论】:

  • 嗨,当我从soapUI 发布它时,它没有序列化,我在输入参数中得到null
  • 然后我需要查看您的 ServiceContract 类和接口,以及您的绑定(如果在 .config 中配置)。
  • 您的 ServiceApplication.IUnderWritingService 是什么样的,因为您的 SoapUI 建议的命名空间与您的示例 XML 不同。哪一个是正确的?
  • 对不起,我是 WCF 新手,所以我对此一无所知,请参阅更新后的问题。
  • 服务契约至少应该有命名空间。查看我的更新
【解决方案2】:

您需要在 Input 类上添加 [DataContract] 属性以使其可序列化。另外,用 [DataMember] 属性装饰这个类的每个属性,你想被序列化。

【讨论】:

  • 我试过那个,但没有成功。你可以找到注释代码。
  • 您是否尝试将 [DataContract] 属性放在类上,因为我在您的代码中看不到它?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-22
相关资源
最近更新 更多