【问题标题】:WCF Web Service serialization error - returning null valuesWCF Web 服务序列化错误 - 返回空值
【发布时间】:2011-09-23 17:47:42
【问题描述】:

我的问题:

我有一个 WCF Web 服务,它被一个简单的 .NET 测试客户端调用,并且正在为正在返回的自定义类的几个属性返回空值。

  • 在返回对象返回之前在断点检查返回对象的值,这表明所有值都已正确填充,但该对象的值在收到后立即显示其几个属性为“空” 。'
  • 我已经阅读了其他几篇关于人们报告相同问题的 stackoverflow 帖子,其中几篇已通过按字母顺序排列/为界面中的 [DataContracts] 分配顺序来解决,但这并没有影响我的结果。
  • 但这些值似乎正在到达客户端程序,因为运行 SoapUI 测试的响应显示 XML 中的正确值。

代码:

[ServiceContract]
public interface IService
{
    [OperationContract]
    TotalTaxResult GetTotalTax(OrderHeader orderHeader);
}

[DataContract]
public class TotalTaxResult
{
    [DataMember]
    public string Message { get; set; }

    [DataMember]
    public ProductLineItem[] ProductLineItems { get; set; }

    [DataMember]
    public string ResultCode { get; set; }

    [DataMember]
    public DataSet ResultDataSet { get; set; }

    [DataMember]
    public string strTaxLinesCount { get; set; }

    [DataMember]
    public DataSet taxDataSet { get; set; }

    [DataMember(IsRequired = true)]
    public decimal TotalTax { get; set; }

    [DataMember]
    public Avalara.AvaTax.Adapter.TaxService.TaxLines TotalTaxLines { get; set; }

}

肥皂请求

     <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tem="http://tempuri.org/" xmlns:sal="http://schemas.datacontract.org/2004/07/SalesService">
   <soapenv:Header/>
   <soapenv:Body>
      <tem:GetTotalTax>
         <!--Optional:-->
         <tem:orderHeader>
            <!--Optional:-->
            <sal:BFCustomerNumber>123456</sal:BFCustomerNumber>
            <!--Optional:-->
            <sal:BFStoreNumber>654321</sal:BFStoreNumber>
            <!--Optional:-->
            <sal:CustomerName>Nick T</sal:CustomerName>
            <!--Optional:-->
            <sal:Message></sal:Message>
            <sal:OrderLineItems>
               <!--Zero or more repetitions:-->
               <sal:OrderLineItem>
                  <sal:ItemNumber>164080</sal:ItemNumber>
                  <sal:LineNumber>1</sal:LineNumber>
                  <sal:Price>100</sal:Price>
                  <sal:Quantity>1</sal:Quantity>
                  <sal:TaxCode>S</sal:TaxCode>
                  <sal:UoM>CA</sal:UoM>
               </sal:OrderLineItem>
            </sal:OrderLineItems>
            <!--Optional:-->
            <sal:PONumber>333000</sal:PONumber>
            <!--Optional:-->
            <sal:ResultCode></sal:ResultCode>
            <!--Optional:-->
            <sal:SourceSystem>WEB</sal:SourceSystem>
            <sal:TestFlag>true</sal:TestFlag>
            <!--Optional:-->
            <sal:TotalTax></sal:TotalTax>
            <!--Optional:-->
            <sal:WarehouseNum>3010</sal:WarehouseNum>
            <!--Optional:-->
            <sal:validDest>
               <!--Optional:-->
               <sal:AddressCode></sal:AddressCode>
               <!--Optional:-->
               <sal:AddressType>S</sal:AddressType>
               <!--Optional:-->
               <sal:CarrierRoute>C022</sal:CarrierRoute>
               <!--Optional:-->
               <sal:City>SAINT LOUIS</sal:City>
               <!--Optional:-->
               <sal:Country>US</sal:Country>
               <!--Optional:-->
               <sal:County>SAINT LOUIS</sal:County>
               <!--Optional:-->
               <sal:FipsCode>2918900000</sal:FipsCode>
               <!--Optional:-->
               <sal:Latitude>30.0000</sal:Latitude>
               <!--Optional:-->
               <sal:Line1>1234 DELMAR DR</sal:Line1>
               <!--Optional:-->
               <sal:Line2></sal:Line2>
               <!--Optional:-->
               <sal:Line3></sal:Line3>
               <!--Optional:-->
               <sal:Line4>SAINT LOUIS MO 63130-6642</sal:Line4>
               <!--Optional:-->
               <sal:Longitude>-95.8765</sal:Longitude>
               <!--Optional:-->
               <sal:PostNet>631306632524</sal:PostNet>
               <!--Optional:-->
               <sal:PostalCode>63130-6642</sal:PostalCode>
               <!--Optional:-->
               <sal:Region>MO</sal:Region>
            </sal:validDest>
            <!--Optional:-->
            <sal:validOrigin>
               <!--Optional:-->
               <sal:AddressCode></sal:AddressCode>
               <!--Optional:-->
               <sal:AddressType>H</sal:AddressType>
               <!--Optional:-->
               <sal:CarrierRoute>R030</sal:CarrierRoute>
               <!--Optional:-->
               <sal:City>SAINT CHARLES</sal:City>
               <!--Optional:-->
               <sal:Country>US</sal:Country>
               <!--Optional:-->
               <sal:County>SAINT CHARLES</sal:County>
               <!--Optional:-->
               <sal:FipsCode>296543210</sal:FipsCode>
               <!--Optional:-->
               <sal:Latitude>35.8034</sal:Latitude>
               <!--Optional:-->
               <sal:Line1>500 ORCHARD LAKES BLVD</sal:Line1>
               <!--Optional:-->
               <sal:Line2></sal:Line2>
               <!--Optional:-->
               <sal:Line3></sal:Line3>
               <!--Optional:-->
               <sal:Line4>SAINT CHARLES MO 63331-4341</sal:Line4>
               <!--Optional:-->
               <sal:Longitude>-95.5021</sal:Longitude>
               <!--Optional:-->
               <sal:PostNet>63389541997</sal:PostNet>
               <!--Optional:-->
               <sal:PostalCode>63331-4341</sal:PostalCode>
               <!--Optional:-->
               <sal:Region>MO</sal:Region>
            </sal:validOrigin>
         </tem:orderHeader>
      </tem:GetTotalTax>
   </soapenv:Body>
</soapenv:Envelope>

肥皂反应:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
   <s:Body>
      <GetTotalTaxResponse xmlns="http://tempuri.org/">
         <GetTotalTaxResult xmlns:a="http://schemas.datacontract.org/2004/07/SalesService" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
            <a:Message>Total Tax Calc</a:Message>
            <a:ProductLineItems i:nil="true"/>
            <a:ResultCode>7.46</a:ResultCode>
            <a:ResultDataSet i:nil="true"/>
            <a:TotalTax>7.46</a:TotalTax>
            <a:TotalTaxLines xmlns:b="http://schemas.datacontract.org/2004/07/Avalara.AvaTax.Adapter.TaxService"/>
            <a:strTaxLinesCount>1</a:strTaxLinesCount>
            <a:taxDataSet>
               <xs:schema id="NewDataSet" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
                  <xs:element name="NewDataSet" msdata:IsDataSet="true" msdata:UseCurrentLocale="true">
                     <xs:complexType>
                        <xs:choice minOccurs="0" maxOccurs="unbounded">
                           <xs:element name="TaxDataTable">
                              <xs:complexType>
                                 <xs:sequence>
                                    <xs:element name="TaxIndex" type="xs:int" minOccurs="0"/>
                                    <xs:element name="TaxLineNo" type="xs:string" minOccurs="0"/>
                                    <xs:element name="TaxCode" type="xs:string" minOccurs="0"/>
                                    <xs:element name="TaxAmount" type="xs:decimal" minOccurs="0"/>
                                 </xs:sequence>
                              </xs:complexType>
                           </xs:element>
                        </xs:choice>
                     </xs:complexType>
                  </xs:element>
               </xs:schema>
               <diffgr:diffgram xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
                  <NewDataSet xmlns="">
                     <TaxDataTable diffgr:id="TaxDataTable1" msdata:rowOrder="0" diffgr:hasChanges="inserted">
                        <TaxIndex>0</TaxIndex>
                        <TaxLineNo>1</TaxLineNo>
                        <TaxCode>P0000000</TaxCode>
                        <TaxAmount>7.46</TaxAmount>
                     </TaxDataTable>
                  </NewDataSet>
               </diffgr:diffgram>
            </a:taxDataSet>
         </GetTotalTaxResult>
      </GetTotalTaxResponse>
   </s:Body>
</s:Envelope>

.NET 客户端结果:

'null' 值:

  • ProductLineItems
  • strTaxLinesCount
  • ResultDataSet 返回为空 DataSet
  • 税数据集
  • TotalTax 返回为“0”
  • TotalTaxLines

具有正确值的唯一属性是:

  • 留言
  • 结果代码

整个过程不抛出异常。

通过 [DataMember(Order=1)] 对接口进行排序不影响结果。相同的属性返回为 null。

如果有人有任何建议,他们将不胜感激。我对 .NET 还很陌生,几天来一直在努力解决这个问题。如果需要任何进一步的信息/代码 sn-ps,请告诉我。提前致谢。

【问题讨论】:

  • WcfTestClient 在这种情况下是你的朋友
  • 我确实经常使用 WCFTestClient,但是这次来自 SoapUI 的额外细节最终解决了我的问题。

标签: c# wcf web-services xml-serialization


【解决方案1】:

希望这能帮助其他真正需要序列化数据集的人,这是我的解决方案。

您不仅应该使用 Serializable 属性,还需要实现 IXmlSerializable 以使自定义类型在数据集中正确序列化。在我实现 IXmlSerializable 之前,我的数据集在自定义类型上带有空白列。

UDT 必须通过遵守 XML 序列化协定来支持与 xml 数据类型之间的转换。 System.Xml.Serialization 命名空间包含用于将对象序列化为 XML 格式文档或流的类。您可以选择使用 IXmlSerializable 接口来实现 xml 序列化,该接口为 XML 序列化和反序列化提供了自定义格式。

除了执行从 UDT 到 xml 的显式转换之外,XML 序列化使您能够:

在转换为 xml 数据类型后对 UDT 实例的值使用 Xquery。

在 SQL Server 中通过本机 XML Web 服务在参数化查询和 Web 方法中使用 UDT。

使用 UDT 接收大量 XML 数据。

对包含具有 UDT 列的表的数据集进行序列化。

UDT 不会在 FOR XML 查询中序列化。要执行显示 UDT 的 XML 序列化的 FOR XML 查询,请在 SELECT 语句中将每个 UDT 列显式转换为 xml 数据类型。您还可以将列显式转换为 varbinary、varchar 或 nvarchar。

http://technet.microsoft.com/en-us/library/ms131082.aspx

IXmlSerializable 的简单实现 http://msdn.microsoft.com/en-us/library/system.xml.serialization.ixmlserializable.aspx

【讨论】:

    【解决方案2】:

    感谢大家的意见。

    我解决了我的问题,但我不完全理解它为什么会起作用。

    我将 TotalTaxResult 的 taxDataSet 属性设置为 DataContract,但我最终没有使用它。只需取出 taxDataSet 属性即可完全解决我的问题。我确定有一条我缺少的 XML 序列化规则。任何防止重复问题的解释都会很棒。

    再次感谢。

    【讨论】:

      【解决方案3】:

      您是如何产生客户的?您可能只需要重新生成或更新您的客户端。例如,如果您生成了客户端,然后将这些属性之一添加到服务器,但没有重新生成客户端,则该值将被传回给客户端,但客户端会忽略它,因为它不知道是什么是的。

      无论如何,这是我最好的猜测......


      实际上,再次阅读您的问题,您表示:

      这些值似乎达到了 客户端程序,因为 运行 SoapUI 测试的响应 在 XML 中显示正确的值。

      但是比较你说的为空的项目列表和肥皂响应:

      • ProductLineItems

      在soap响应中为空:

      <a:ProductLineItems i:nil="true"/>
      
      • TotalTaxLines

      在soap响应中为空:

      <a:TotalTaxLines xmlns:b="http://schemas.datacontract.org/2004/07/Avalara.AvaTax.Adapter.TaxService"/>
      

      所以我必须假设那些实际上正确返回 null。


      另外,对于包含这些非标准数据类型的属性:

      • ProductLineItem
      • Avalara.AvaTax.Adapter.TaxService.TaxLines

      这两种数据类型也需要我标记为 [DataContract],否则我认为 ISerializable 也可以工作。

      【讨论】:

      • 对不起,您对 ProductLineItems 和 TotalTaxLines 的看法是正确的,它们不应该为空。 ProductLineItems 被标记为 [DataContract] 但 TaxLines 没有。我对 Web 服务的定义在客户端更新,这是一个简单的应用程序,添加了 Web 服务作为 Web 参考,这就是我提供测试数据的方式。此外 TotalTaxResult.ToxalTax 两边都是小数,但仍默认为 0,但不为空。
      【解决方案4】:

      ProductLineItem 和 TaxLines 字段也被假定为被标记为序列化/DataCotnracts。如果没有,您必须标记它们。关于数据集。只有当服务器(十进制)和客户端(其他)上的数据类型不同时,总税才能变为 0,您必须检查客户端正在使用的接口(如果这不是代理)。 关于数据集也是如此,我过去在使用 DataSet 时遇到了一些问题,只有当 DataSet 类型不在引用库列表中时,所以 .NET 必须使用代理类型。

      【讨论】:

      • TotalTax 是服务端和客户端的小数,ProductLineItem 被标记为 DataContract,TaxLines 到目前为止不是,但我会尝试。您还记得您是如何解决数据集问题的吗?感谢您的回复。
      • 我们通过将服务合同接口移动到单独的库(连同它所使用的类型)并将该库发送给客户端来解决客户端的问题。顺便说一下,这比使用自动生成的代理更好。我希望它有所帮助..
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-11
      • 1970-01-01
      • 1970-01-01
      • 2023-03-08
      • 1970-01-01
      相关资源
      最近更新 更多