Ошибка сериализации веб-службы WCF - возвращаются нулевые значения - PullRequest
6 голосов
/ 27 июня 2011

Моя проблема:

У меня есть веб-служба WCF, которая вызывается простым тестовым клиентом .NET и возвращает нулевые значения для некоторых свойств пользовательского класса, которыевозвращается

  • Проверка значений возвращаемого объекта в точке останова непосредственно перед его возвратом показывает мне, что все значения заполнены правильно, но значение этого объекта, как только оно получено, показывает несколькоего свойства равны 'null.'
  • Я прочитал несколько других сообщений от стека-потока людей, сообщающих об одной и той же проблеме, и некоторые из них были решены путем алфавитизации / назначения порядка [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 Client Результаты:

'нулевые' значения для:

  • ProductLineItems
  • strTaxLinesCount
  • ResultDataSet возвращается какпустой DataSet
  • taxDataSet
  • TotalTax возвращается как '0'
  • TotalTaxLines

Единственные свойства с их правильными значениями:

  • Сообщение
  • ResultCode

Никаких исключений не выдается в течение всего процесса.

Порядок интерфейса через [DataMember (Order = 1)] не влияет на результаты.Те же свойства возвращены как null.

Если у кого-то есть предложения, они будут очень благодарны.Я довольно новичок в .NET и уже несколько дней бьюсь над этой проблемой.Если вам нужна дополнительная информация / фрагменты кода, пожалуйста, дайте мне знать.Заранее спасибо.

Ответы [ 4 ]

4 голосов
/ 27 июня 2011

Как вы создали свой клиент?Возможно, вам просто нужно восстановить или обновить ваш клиент.Например, если вы сгенерировали клиент, а затем добавили одно из этих свойств на сервер, но не регенерировали клиент, тогда значение будет возвращено клиенту, но клиент проигнорирует его, потому что не знает, чтоэто так.

В любом случае, это мое лучшее предположение ...


На самом деле, читая ваш вопрос еще раз, вы заявили, что:

Значенияпохоже, что он достигает клиентской программы, потому что ответ от запуска теста SoapUI показывает правильные значения в XML.

Однако сравнение списка элементов, которые вы говорите, является нулевым, и ответ мыла:

  • ProductLineItems

В ответе мыла указано NULL:

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

Нуль вответ мыла:

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

Так что я должен предположить, что они на самом деле правильно возвращают ноль.


Кроме того, для свойств, которые содержат эти нестандартные типы данных:

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

Эти два типа данных должны быть помечены как [DataContract], или я думаю, что ISerializable также будет работать.

0 голосов
/ 18 августа 2012

В надежде, что это поможет другим, кому действительно нужно сериализовать набор данных, это мое решение.

Мало того, что вы должны использовать атрибут Serializable, вам также нужно реализовать IXmlSerializable для того, чтобы пользовательский тип правильно сериализовался в наборе данных. Мои наборы данных возвращались с пустыми столбцами в пользовательских типах, пока я не реализовал IXmlSerializable.

UDT должны поддерживать преобразование в тип данных xml и обратно в соответствии с контрактом на сериализацию XML. Пространство имен System.Xml.Serialization содержит классы, которые используются для сериализации объектов в документы или потоки в формате XML. Вы можете реализовать сериализацию xml с помощью интерфейса IXmlSerializable, который обеспечивает настраиваемое форматирование для сериализации и десериализации XML.

В дополнение к выполнению явных преобразований из UDT в xml, XML-сериализация позволяет вам:

Использовать Xquery для значений экземпляров UDT после преобразования в тип данных xml.

Использование UDT в параметризованных запросах и веб-методах с собственными веб-службами XML в SQL Server.

Использование UDT для получения массовой загрузки данных XML.

Сериализация наборов данных, содержащих таблицы со столбцами UDT.

UDT не сериализуются в запросах FOR XML. Чтобы выполнить запрос FOR XML, который отображает сериализацию UDT в формате XML, явным образом преобразуйте каждый столбец UDT в тип данных xml в инструкции SELECT. Вы также можете явно преобразовать столбцы в 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

0 голосов
/ 28 июня 2011

Спасибо всем за вклад.

Я исправил свою проблему, хотя я не совсем понимаю, почему она работала.

У меня было свойство taxDataSet TotalTaxResult, настроенное как DataContract, но я не стал его использовать.Простое удаление свойства taxDataSet полностью решило мою проблему.Я уверен, что есть правило сериализации XML, которое мне не хватает.Любое объяснение, чтобы предотвратить повторную проблему было бы здорово.

Еще раз спасибо.

0 голосов
/ 27 июня 2011

Поля ProductLineItem и TaxLines также должны быть помечены как сериализованные / DataCotnracts.Если нет, вы должны пометить их.По поводу наборов данных.Суммарный налог может стать 0 только в том случае, если типы данных на сервере (десятичные) и клиенте (что-то еще) различаются, необходимо проверить интерфейс, с которым работает клиент (если это не прокси-сервер).То же самое с наборами данных, с которыми я сталкивался в прошлом с DataSets, только когда тип DataSet отсутствует в списке библиотек, на которые есть ссылки, поэтому .NET должен работать с прокси-типом.

...