locked
How to assing KnownTypeAttribute on WinRT RRS feed

  • Question

  • Hi. Some Java REST service that I'm trying to consume either with a WinRT and Windows phone client is generating the next XML on the response:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
      <applicationResponse>
        <content>
          <data xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="usuarioType">
            <usuario>+++++</usuario>
            <nombre>+++++</nombre>
            <apellidos>+++++</apellidos>
          </data>
        </content>
        <livingTime>16</livingTime>
      </applicationResponse>

    This configuration is fixed and I have no capability to change it. I'm trying to deserialize the response with DataContractSerializer object, and I always get an exception related with the defined type on data node. I solved the problem in another Project (console application , NET. fw 4.5) with a DataContractResolver, but this kind of object doesn't exist in WinRT or Windows Phone. I'm trying to use KnownType attribute, but still doesn't work. What I'm doing wrong?

    The class definitions I'm using for deserialize the object are:

        [DataContract(Name = "data")]
        [KnownType(typeof(usuarioType))]
        public class usuarioType
        {
            [DataMember(Name="usuario",Order=1)]
            public string usuario { get; set; }
            [DataMember(Name = "nombre",Order=2)]
            public string nombre { get; set; }
            [DataMember(Name = "apellidos",Order=3)]
            public string apellidos { get; set; }
        }
        [DataContract(Name = "content", Namespace = "")]
        public partial class Content
        {
            [DataMember(Name = "data")]
            public usuarioType data { get; set; }
        }
        [DataContract(Name = "applicationResponse", Namespace = "")]
        public class ApplicationResponse
        {
            [DataMember(Name = "content")]
            public Content content { get; set; }
            [DataMember(Name = "livingTime")]
            public int livingTime { get; set; }
        }

    Thanks

    Thursday, August 22, 2013 12:06 PM

Answers

  • This was suggested:

    Try changing the DataContract attribute declaration on the usuarioType class to

        [DataContract(Name = "usuarioType", Namespace = "")]


    Matt Small - Microsoft Escalation Engineer - Forum Moderator
    If my reply answers your question, please mark this post as answered.

    NOTE: If I ask for code, please provide something that I can drop directly into a project and run (including XAML), or an actual application project. I'm trying to help a lot of people, so I don't have time to figure out weird snippets with undefined objects and unknown namespaces.

    Friday, August 23, 2013 4:58 PM
    Moderator
  • Hi,

    Please could you check the solution here http://sdrv.ms/17743jP

    This contains a PCL with deserialization code + 2 client apps; one is a wp8 app and the other a windows store c# app. The code uses the previously suggested fix and works when I run in my wp8 emulator and as a native windows store app running from visual studio. Could you try it and report back any exceptions?  


    http://babaandthepigman.spaces.live.com/blog/

    Monday, August 26, 2013 1:18 PM

All replies

  • I know about nothing in XML, but I'll see if I can find someone who know this.  We really need an XML expert for the Win8 forums. :-)  I'll update when I can.

    Matt Small - Microsoft Escalation Engineer - Forum Moderator
    If my reply answers your question, please mark this post as answered.

    NOTE: If I ask for code, please provide something that I can drop directly into a project and run (including XAML), or an actual application project. I'm trying to help a lot of people, so I don't have time to figure out weird snippets with undefined objects and unknown namespaces.

    Friday, August 23, 2013 12:37 PM
    Moderator
  • This was suggested:

    Try changing the DataContract attribute declaration on the usuarioType class to

        [DataContract(Name = "usuarioType", Namespace = "")]


    Matt Small - Microsoft Escalation Engineer - Forum Moderator
    If my reply answers your question, please mark this post as answered.

    NOTE: If I ask for code, please provide something that I can drop directly into a project and run (including XAML), or an actual application project. I'm trying to help a lot of people, so I don't have time to figure out weird snippets with undefined objects and unknown namespaces.

    Friday, August 23, 2013 4:58 PM
    Moderator
  • Same exception in Windows Phone and WinRT without DataContractResolver.
    Monday, August 26, 2013 9:38 AM
  • At last I could add a DataContractResolver both in WinRT and Windows Phone 8, but only worked in WinRT, in WP8 seems that overriden ResolveName method isn't used. Source code is:

        [DataContract(Name = "data",Namespace="")]
        [KnownType(typeof(usuarioType))]
        public class usuarioType
        {
            [DataMember(Name = "usuario", Order = 1)]
            public string usuario { get; set; }
            [DataMember(Name = "nombre", Order = 2)]
            public string nombre { get; set; }
            [DataMember(Name = "apellidos", Order = 3)]
            public string apellidos { get; set; }
        }
    
        [DataContract(Name = "content", Namespace = "")]
        public partial class Content
        {
            [DataMember(Name = "data")]
            public usuarioType data { get; set; }
        }
        [DataContract(Name = "applicationResponse", Namespace = "")]
        public class ApplicationResponse
        {
            [DataMember(Name = "content")]
            public Content content { get; set; }
            [DataMember(Name = "livingTime")]
            public int livingTime { get; set; }
        }
    
    
        public class usuarioTypeResolver : DataContractResolver
        {
            public override bool TryResolveType(Type dataContractType, Type declaredType, DataContractResolver knownTypeResolver, out XmlDictionaryString typeName, out XmlDictionaryString typeNamespace)
            {
                if (dataContractType == typeof(usuarioType))
                {
                    XmlDictionary dictionary = new XmlDictionary();
                    typeName = dictionary.Add("usuarioType");
                    typeNamespace = dictionary.Add("http://www.w3.org/2001/XMLSchema-instance");
                    return true;
                }
                else
                {
                    return knownTypeResolver.TryResolveType(dataContractType, declaredType, null, out typeName, out typeNamespace);
                }
            }
    
            public override Type ResolveName(string typeName, string typeNamespace, Type declaredType, DataContractResolver knownTypeResolver)
            {
                return typeof(usuarioType);
            }
    
        }

    And code for using these classes is:

                ApplicationResponse result;
    
                string xmlResp = @"<?xml version='1.0' encoding='UTF-8' standalone='yes'?><applicationResponse><content><data xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xsi:type='usuarioType'><usuario>++++++</usuario><nombre>+++++++</nombre><apellidos>++++++++</apellidos></data></content><livingTime>16</livingTime></applicationResponse> ";
                List<Type> knownTypeList = new List<Type>();
                knownTypeList.Add(typeof(usuarioType));
                DataContractSerializerSettings sets = new DataContractSerializerSettings();
    
    
                usuarioTypeResolver resl = new usuarioTypeResolver();
                sets.DataContractResolver = resl;
                sets.KnownTypes = knownTypeList;
    
                DataContractSerializer obj = new DataContractSerializer(typeof(ApplicationResponse), sets);
    
                byte[] byteArray = Encoding.UTF8.GetBytes(xmlResp);
                MemoryStream stream = new MemoryStream(byteArray);
                result = obj.ReadObject(stream) as ApplicationResponse;
    
                //XmlDictionaryReader re = XmlDictionaryReader.CreateDictionaryReader(XmlReader.Create(stream));
                //result = obj.ReadObject(re,false) as ApplicationResponse;

    In my project the stream is the result of a request to a Java Rest service made with SPRING. The idea is to encapsulate the same code in a Portable Class Library, but only works with WinRT.
    Monday, August 26, 2013 11:16 AM
  • Hi,

    Please could you check the solution here http://sdrv.ms/17743jP

    This contains a PCL with deserialization code + 2 client apps; one is a wp8 app and the other a windows store c# app. The code uses the previously suggested fix and works when I run in my wp8 emulator and as a native windows store app running from visual studio. Could you try it and report back any exceptions?  


    http://babaandthepigman.spaces.live.com/blog/

    Monday, August 26, 2013 1:18 PM
  • Ok, works perfect. Same as told Matt Just change DataContract Name from "data" to "usuarioType", without DataContractResolver and list of KnownTypes (don't know why yesterday failed on my code). And still works with DatacontractJsonSerializer (we have two REST services), sharing the same class definitions.

    Thanks a lot.

    Tuesday, August 27, 2013 10:16 AM
  • You're welcome - glad to know you have a working solution :)

    http://babaandthepigman.spaces.live.com/blog/

    Tuesday, August 27, 2013 10:59 AM