tags:

views:

3280

answers:

4

Hello, I want a Web Service in C# that returns a Dictionary, according to a search:

Dictionary<int, string> GetValues(string search) {}

The Web Service compiles fine, however, when i try to reference it, i get the following error: "is not supported because it implements IDictionary."

¿What can I do in order to get this working?, any ideas not involving return a DataTable?

+1  A: 

Create a type MyKeyValuePair<K,V>, and return a List<MyKeyValuePair<int,string>>, copied from the dictionary.

John Saunders
Might use the standard KeyValuePair just as well.
Anton Tykhyy
I'm going to try then
Jhonny D. Cano -Leftware-
I don't recall the specifics, but I had a problem with that class. Hence my "reinvented wheel".
John Saunders
I don't know why I didn't post http://johnwsaundersiii.spaces.live.com/blog/cns!600A2BE4A82EA0A6!699.entry earlier. I had created it two weeks earlier.
John Saunders
+1  A: 

This article has a method to serialize IDictionaries. Look for " I've noticed that XmlSerializer won't serialize objects that implement IDictionary by default. Is there any way around this?" about 2/3 the way down the page.

Moose
Your link says "Sorry, we were unable to service your request."
Sarah Vessels
The method provided at that link (which I can access at time of writing) simply uses ToString, so it's only useful for a Dictionary with String keys and values.
Warren Blanchet
+1  A: 

I use this util class for serializing dictionaries, maybe it can be useful for you

using System.Collections.Generic;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;

namespace Utils {
    ///<summary>
    ///</summary>
    public class SerializableDictionary : IXmlSerializable {
     private readonly IDictionary<int, string> dic;
     public DiccionarioSerializable() {
      dic = new Dictionary<int, string>();
     }
     public SerializableDictionary(IDictionary<int, string> dic) {
      this.dic = dic;
     }
     public IDictionary<int, string> Dictionary {
      get { return dic; }
     }
     public XmlSchema GetSchema() {
      return null;
     }
     public void WriteXml(XmlWriter w) {
      w.WriteStartElement("dictionary");
      foreach (int key in dic.Keys) {
       string val = dic[key];
       w.WriteStartElement("item");
       w.WriteElementString("key", key.ToString());
       w.WriteElementString("value", val);
       w.WriteEndElement();
      }
      w.WriteEndElement();
     }
     public void ReadXml(XmlReader r) {
      if (r.Name != "dictionary") r.Read(); // move past container
      r.ReadStartElement("dictionary");
      while (r.NodeType != XmlNodeType.EndElement) {
       r.ReadStartElement("item");
       string key = r.ReadElementString("key");
       string value = r.ReadElementString("value");
       r.ReadEndElement();
       r.MoveToContent();
       dic.Add(Convert.ToInt32(key), value);
      }
     }
    }
}
+5  A: 

There's no "default" way to take a Dictionary and turn it into XML. You have to pick a way, and your web service's clients will have to be aware of that same way when they are using your service. If both client and server are .NET, then you can simply use the same code to serialize and deserialize Dictionaries to XML on both ends.

There's code to do this in this blog post. This code uses the default serialization for the keys and values of the Dictionary, which is useful when you have non-string types for either. The code uses inheritance to do its thing (you have to use that subclass to store your values). You could also use a wrapper-type approach as done in the last item in this article, but note that the code in that article just uses ToString, so you should combine it with the first article.

Because I agree with Joel about StackOverflow being the canonical source for everything, below is a copy of the code from the first link. If you notice any bugs, edit this answer!

using System;
using System.Collections.Generic;
using System.Text;
using System.Xml.Serialization;

[XmlRoot("dictionary")]
public class SerializableDictionary<TKey, TValue> : Dictionary<TKey, TValue>, IXmlSerializable
{
    #region IXmlSerializable Members

    public System.Xml.Schema.XmlSchema GetSchema()
    {
        return null;
    }

    public void ReadXml(System.Xml.XmlReader reader)
    {
        XmlSerializer keySerializer = new XmlSerializer(typeof(TKey));
        XmlSerializer valueSerializer = new XmlSerializer(typeof(TValue));

        bool wasEmpty = reader.IsEmptyElement;
        reader.Read();

        if (wasEmpty)
            return;

        while (reader.NodeType != System.Xml.XmlNodeType.EndElement)
        {
            reader.ReadStartElement("item");

            reader.ReadStartElement("key");
            TKey key = (TKey)keySerializer.Deserialize(reader);
            reader.ReadEndElement();

            reader.ReadStartElement("value");
            TValue value = (TValue)valueSerializer.Deserialize(reader);
            reader.ReadEndElement();

            this.Add(key, value);

            reader.ReadEndElement();

            reader.MoveToContent();
        }

        reader.ReadEndElement();
    }

    public void WriteXml(System.Xml.XmlWriter writer)
    {
        XmlSerializer keySerializer = new XmlSerializer(typeof(TKey));
        XmlSerializer valueSerializer = new XmlSerializer(typeof(TValue));

        foreach (TKey key in this.Keys)
        {
            writer.WriteStartElement("item");

            writer.WriteStartElement("key");
            keySerializer.Serialize(writer, key);
            writer.WriteEndElement();

            writer.WriteStartElement("value");
            TValue value = this[key];
            valueSerializer.Serialize(writer, value);
            writer.WriteEndElement();

            writer.WriteEndElement();
        }
    }

    #endregion
}
Warren Blanchet