【问题标题】:SOAP response containing SERIALIZED DICTIONARY is not valid in SoapUI包含 SERIALIZED DICTIONARY 的 SOAP 响应在 SoapUI 中无效
【发布时间】:2013-09-10 09:10:18
【问题描述】:

我的 web 服务没有任何其他属性,除了字典,我以这种方式序列化。

 public class DictionarySerializer : IXmlSerializable
    {
         private IDictionary dictionary;

    public DictionarySerializer()
    {
        this.dictionary = new Hashtable();
    }

    public DictionarySerializer(IDictionary dictionary)
    {
        this.dictionary = dictionary;
    }

    public void addToDict(object key, object value)
    {
        this.dictionary.Add(key, value);
    }

    public static void Serialize(IDictionary dictionary, Stream stream)
    {
        DictionarySerializer ds = new DictionarySerializer(dictionary);
        XmlSerializer xs = new XmlSerializer(typeof(DictionarySerializer));
        xs.Serialize(stream, ds);
    }

    public static IDictionary Deserialize(Stream stream)
    {
        XmlSerializer xs = new XmlSerializer(typeof(DictionarySerializer));
        DictionarySerializer ds = (DictionarySerializer)xs.Deserialize(stream);
        return ds.dictionary;
    }

    XmlSchema IXmlSerializable.GetSchema()
    {
        return (null);
    }

    void IXmlSerializable.ReadXml(XmlReader reader)
    {
        reader.Read();
        reader.ReadStartElement("dictionary");
        while (reader.NodeType != XmlNodeType.EndElement)
        {
            reader.ReadStartElement("item");
            string key = reader.ReadElementString("key");
            string value = reader.ReadElementString("value");
            reader.ReadEndElement();
            reader.MoveToContent();
            dictionary.Add(key, value);
        }
        reader.ReadEndElement();
    }

    void IXmlSerializable.WriteXml(XmlWriter writer)
    {
        foreach (object key in dictionary.Keys)
        {
            object value = dictionary[key];
            writer.WriteStartElement(key.ToString());
            writer.WriteValue(value.ToString()); //WriteElementString("value", value.ToString());
            writer.WriteEndElement();
        }            
    }
    }

在我的 WS 中,我以这种方式动态地用属性填充我的字典

            this.DICTIONARY.addToDict("WARRANTY", drv["Warranty"].ToString());
            this.DICTIONARY.addToDict("IMAGEURL", drv["ImageUrl"].ToString());
            this.DICTIONARY.addToDict("RETAILPRICE", drv["RetailPrice"].ToString());

并且我能够使用包含此字典元素的 SoapUI 获得响应:

<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>
      <GetProductsResponse xmlns="http://www.xxx.com/B2B">
         <GetProductsResult>
            <PRODUCT>
               <DICTIONARY>
                  <IMAGE_URL>888009612_1.jpg</IMAGE_URL>
                  <WARRANTY>1G</WARRANTY>
                  <RETAILPRICE>0.00000000000000000000</RETAILPRICE>
               </DICTIONARY>
            </PRODUCT>
         </GetProductsResult>
      </GetProductsResponse>
   </soap:Body>
</soap:Envelope>

问题是响应对 wsdl 架构无效!这是我描述字典的 wsdl 的一部分:

<s:element name="GetProductsResponse">
        <s:complexType>
          <s:sequence>
            <s:element minOccurs="0" maxOccurs="1" name="GetProductsResult" type="tns:ArrayOfPRODUCT" />
          </s:sequence>
        </s:complexType>
      </s:element>
      <s:complexType name="ArrayOfPRODUCT">
        <s:sequence>
          <s:element minOccurs="0" maxOccurs="unbounded" name="PRODUCT" nillable="true" type="tns:PRODUCT" />
        </s:sequence>
      </s:complexType>
      <s:complexType name="PRODUCT">
        <s:sequence>
          <s:element minOccurs="0" maxOccurs="1" name="DICTIONARY">
            <s:complexType>
              <s:sequence>
                <s:element ref="s:schema" />
                <s:any />
              </s:sequence>
            </s:complexType>
          </s:element>
        </s:sequence>
      </s:complexType>

我在 SoapUI 中遇到的错误是这样的

Expected element 'schema@http://www.w3.org/2001/XMLSchema' instead of 'WARRANTY@http://www.xxx.com/B2B' here in element DICTIONARY@http://www.xxx.com/B2B
Expected element 'schema@http://www.w3.org/2001/XMLSchema' instead of 'RETAILPRICE@http://www.xxx.com/B2B' here in element DICTIONARY@http://www.xxx.com/B2B
Expected element 'schema@http://www.w3.org/2001/XMLSchema' before the end of the content in element DICTIONARY@http://www.xxx.com/B2B

这让我很困惑。我不知道这个错误是什么意思以及如何解决这个问题,以便我的响应对 wsdl 有效。你能帮我解决这个问题吗???

ps.

这是一个旧的 .asmx Web 服务,需要一些修饰。我是否要使用 wcf 编写此服务来解决这个问题?

感谢您的任何想法。

【问题讨论】:

    标签: web-services serialization wsdl xsd soapui


    【解决方案1】:

    至少部分问题是由于字典序列化代码:反序列化需要这样的东西:

    <dictionary>
      <item>
        <key>the key</key>
        <value>the value</value>
      </item>
      ...
    </dictionary>
    

    但序列化代码生成:

    <dictionary>
      <the key>the value</the key>
       . . . 
    </dictionary>
    

    序列化应该是这样的:

    void IXmlSerializable.WriteXml(XmlWriter writer)
    {
        foreach (object key in dictionary.Keys)
        {
            object value = dictionary[key];
            writer.WriteStartElement("item");
            writer.WriteElementString("key", key.ToString());
            writer.WriteElementString("value", value.ToString());
            writer.WriteEndElement();
        }            
    }
    

    【讨论】:

    • 感谢您的回复。我试过这个,现在我的soapresponse看起来像这样(sn-p):&lt;item&gt; &lt;key&gt;WARRANTY&lt;/key&gt; &lt;value&gt;1G&lt;/value&gt; &lt;/item&gt; &lt;item&gt; &lt;key&gt;RETAILPRICE&lt;/key&gt; &lt;value&gt;0.00000000000000000000&lt;/value&gt; &lt;/item&gt;但我仍然收到错误预期元素'schema@w3.org/2001/XMLSchema'而不是'item@something.com/B2B'在元素DICTIONARY中@something.com/B2B
    【解决方案2】:

    如果有人对此感兴趣,我已经自己解决了这个问题。因为 XMLSchema 需要的是字符串,而不是 List,所以我以这种方式给了它一个字符串。

    public string GetProducts(List<Product> lstProducts){
        string textReaderText = "";
        XmlSerializer SerializerObj = new XmlSerializer(typeof(List<Product>));
        TextWriter WriteFileStream = new StringWriter(new System.Text.StringBuilder(textReaderText));
        SerializerObj.Serialize(WriteFileStream, lstProducts);
        WriteFileStream.Close();
        string stringresult = WriteFileStream.ToString();
        return stringresult;
    }
    

    这已经解决了!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-04-05
      • 1970-01-01
      • 1970-01-01
      • 2012-03-26
      • 2021-05-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多