Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C#
  4. Object "type not expected" when using serialization in web services

Object "type not expected" when using serialization in web services

Scheduled Pinned Locked Moved C#
helptutorialwcfsysadminxml
6 Posts 2 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • B Offline
    B Offline
    BASONJS
    wrote on last edited by
    #1

    Hi all, Hope I am posting this in the right forum. I seem to be having a problem when using serialization and web services. Scenario: I have built a web service which includes a multitude of web methods. All the web methods have various parameters, but one parameter which they all have in common is an 'object' parameter. This is due to the fact that the web service works differently according to the type of object being passed into it. Now as for the objects, I have constructed a set of custom classes which satisfy my need. For example's sake, let us say we have: Teacher class Student Class LectureRoom Class Lecture Class We will call these the "School Package classes" I am then wrapping these classes within other custom classes which I use not only to transport my objects around but also to keep track of statuses etc. Example: Request Class Response Class The school package classes would be serialized and saved within the request or response class. So effectively, the objects which the web service really sees are the request and response classes which will in turn have the school package classes inside of them. The Problem: The problem is found when a school package object is passed within the response and request object. On deserialisation or transportation of these objects, the web service always throws an exception as follows: {"System.Web.Services.Protocols.SoapException: Server was unable to process request. ---> System.InvalidOperationException: There was an error generating the XML document. ---> System.InvalidOperationException: The type was not expected. Use the XmlInclude or SoapInclude attribute to specify types that are not known statically. From what I could gather and the research I have done, the problem lies with the web service not knowing of the object types at compile time. Make Shift Solution: For a quick and dirty solution I created methods within the web service which use the object types needed. For Example: public void Junk(Student myStudent){} This seemed to have worked, but is not what I want, as with about 40 custom classes, this is both horrible coding and very tedious. I have also tried researching the xmlinclude and soapinclude found in the System.Xml.Serialization library, but dont really know how to use these. I have tried adding them above the web service class declaration and the web methods which use the objects in this format: [XmlInclude(typeof(Student))] But yet to no

    T 1 Reply Last reply
    0
    • B BASONJS

      Hi all, Hope I am posting this in the right forum. I seem to be having a problem when using serialization and web services. Scenario: I have built a web service which includes a multitude of web methods. All the web methods have various parameters, but one parameter which they all have in common is an 'object' parameter. This is due to the fact that the web service works differently according to the type of object being passed into it. Now as for the objects, I have constructed a set of custom classes which satisfy my need. For example's sake, let us say we have: Teacher class Student Class LectureRoom Class Lecture Class We will call these the "School Package classes" I am then wrapping these classes within other custom classes which I use not only to transport my objects around but also to keep track of statuses etc. Example: Request Class Response Class The school package classes would be serialized and saved within the request or response class. So effectively, the objects which the web service really sees are the request and response classes which will in turn have the school package classes inside of them. The Problem: The problem is found when a school package object is passed within the response and request object. On deserialisation or transportation of these objects, the web service always throws an exception as follows: {"System.Web.Services.Protocols.SoapException: Server was unable to process request. ---> System.InvalidOperationException: There was an error generating the XML document. ---> System.InvalidOperationException: The type was not expected. Use the XmlInclude or SoapInclude attribute to specify types that are not known statically. From what I could gather and the research I have done, the problem lies with the web service not knowing of the object types at compile time. Make Shift Solution: For a quick and dirty solution I created methods within the web service which use the object types needed. For Example: public void Junk(Student myStudent){} This seemed to have worked, but is not what I want, as with about 40 custom classes, this is both horrible coding and very tedious. I have also tried researching the xmlinclude and soapinclude found in the System.Xml.Serialization library, but dont really know how to use these. I have tried adding them above the web service class declaration and the web methods which use the objects in this format: [XmlInclude(typeof(Student))] But yet to no

      T Offline
      T Offline
      Thomas ST
      wrote on last edited by
      #2

      How do you annotate your custom objects to make them serializable? Something like this? :

      [System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://namespace/", TypeName = "person")]
      public class Person
      {
      private string _name;

      [System.Xml.Serialization.XmlElementAttribute(ElementName = "name")]
      public string Name { get { return _name; } }
      }

      And are you sure that you don't have any namespace-conflicts between your custom objects?

      B 1 Reply Last reply
      0
      • T Thomas ST

        How do you annotate your custom objects to make them serializable? Something like this? :

        [System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://namespace/", TypeName = "person")]
        public class Person
        {
        private string _name;

        [System.Xml.Serialization.XmlElementAttribute(ElementName = "name")]
        public string Name { get { return _name; } }
        }

        And are you sure that you don't have any namespace-conflicts between your custom objects?

        B Offline
        B Offline
        BASONJS
        wrote on last edited by
        #3

        no at the moment the objects are as follows:

        using System;
        using System.Runtime.Serialization;
        using Person;

        namespace SchoolPackage
        {
        [Serializable()]
        public class Student : ISerializable
        {
        private Person person;
        private int intReference;
        private int intReqTypeID;
        //
        private string strLastAlteredByUser;
        private DateTime dteAlteredDate;
        private Boolean blnIsDirty;
        private Boolean blnIsNew;
        private enum RequestType : int
        {
        Create = 1, Delete = 2, Update = 3, Execute = 4,
        Retrieve = 5, RetrieveMultiple = 6
        }

            public Student(Person person, String user, int TypeID, int Reference) 
            {
                this.person = person;
                this.strLastAlteredByUser = user;
                this.dteAlteredDate = DateTime.Now;
                this.blnIsDirty = false;
                this.blnIsNew = true;
                this.intReqTypeID = TypeID;
                this.intReference = Reference;
            }
          
            //Deserialization constructor.
            public Student(SerializationInfo info, StreamingContext ctxt)
            {
                //Get the values from info and assign them to the appropriate properties
                person = (Person)info.GetValue("person", typeof(Person));
                action = (string)info.GetValue("action", typeof(string));
                intReference = (int)info.GetValue("intReference", typeof(int));
                intReqTypeID = (int)info.GetValue("intReqTypeID", typeof(int));
            }
                    
            //Serialization function.
            public void GetObjectData(SerializationInfo info, StreamingContext ctxt)
            {            
                info.AddValue("person", person);
                info.AddValue("action", action);
                info.AddValue("intReference", intReference);
                info.AddValue("intReqTypeID", intReqTypeID);
            }
        

        }

        T 1 Reply Last reply
        0
        • B BASONJS

          no at the moment the objects are as follows:

          using System;
          using System.Runtime.Serialization;
          using Person;

          namespace SchoolPackage
          {
          [Serializable()]
          public class Student : ISerializable
          {
          private Person person;
          private int intReference;
          private int intReqTypeID;
          //
          private string strLastAlteredByUser;
          private DateTime dteAlteredDate;
          private Boolean blnIsDirty;
          private Boolean blnIsNew;
          private enum RequestType : int
          {
          Create = 1, Delete = 2, Update = 3, Execute = 4,
          Retrieve = 5, RetrieveMultiple = 6
          }

              public Student(Person person, String user, int TypeID, int Reference) 
              {
                  this.person = person;
                  this.strLastAlteredByUser = user;
                  this.dteAlteredDate = DateTime.Now;
                  this.blnIsDirty = false;
                  this.blnIsNew = true;
                  this.intReqTypeID = TypeID;
                  this.intReference = Reference;
              }
            
              //Deserialization constructor.
              public Student(SerializationInfo info, StreamingContext ctxt)
              {
                  //Get the values from info and assign them to the appropriate properties
                  person = (Person)info.GetValue("person", typeof(Person));
                  action = (string)info.GetValue("action", typeof(string));
                  intReference = (int)info.GetValue("intReference", typeof(int));
                  intReqTypeID = (int)info.GetValue("intReqTypeID", typeof(int));
              }
                      
              //Serialization function.
              public void GetObjectData(SerializationInfo info, StreamingContext ctxt)
              {            
                  info.AddValue("person", person);
                  info.AddValue("action", action);
                  info.AddValue("intReference", intReference);
                  info.AddValue("intReqTypeID", intReqTypeID);
              }
          

          }

          T Offline
          T Offline
          Thomas ST
          wrote on last edited by
          #4

          System.Runtime.Serialization is used for binary serialization. Since Webservices use Soap wich is xml, you should serialize objects to xml. Read this article on msdn about XML Serialization with XML Web Services. In your example, just import System.Xml.Serialization and add the annotation [System.Xml.Serialization.XmlTypeAttribute()]. And make public accessors to the members you want to be serialized.

          using System;
          using System.Runtime.Serialization;
          using Person;
          using System.Xml;
          using System.Xml.Serialization;

          namespace SchoolPackage
          {
          //This line is basically all you need for the class to be serializable
          [System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://www.x.com/namespace/", TypeName = "Student")]
          public class Student
          {
          [System.Xml.Serialization.XmlElementAttribute(ElementName = "myCustomXmlElementName")]
          public string StrLastAlteredByUser
          {
          get { return strLastAlteredByUser; }
          set { strLastAlteredByUser = value; }
          }
          }
          }

          ps. personally I would let Student inherit Person :)

          B 1 Reply Last reply
          0
          • T Thomas ST

            System.Runtime.Serialization is used for binary serialization. Since Webservices use Soap wich is xml, you should serialize objects to xml. Read this article on msdn about XML Serialization with XML Web Services. In your example, just import System.Xml.Serialization and add the annotation [System.Xml.Serialization.XmlTypeAttribute()]. And make public accessors to the members you want to be serialized.

            using System;
            using System.Runtime.Serialization;
            using Person;
            using System.Xml;
            using System.Xml.Serialization;

            namespace SchoolPackage
            {
            //This line is basically all you need for the class to be serializable
            [System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://www.x.com/namespace/", TypeName = "Student")]
            public class Student
            {
            [System.Xml.Serialization.XmlElementAttribute(ElementName = "myCustomXmlElementName")]
            public string StrLastAlteredByUser
            {
            get { return strLastAlteredByUser; }
            set { strLastAlteredByUser = value; }
            }
            }
            }

            ps. personally I would let Student inherit Person :)

            B Offline
            B Offline
            BASONJS
            wrote on last edited by
            #5

            I have done as you suggested and am still getting the same error. The problem now I believe is the way I am serialising the object. I have made a custom class for this: using System; using System.Text; namespace Helper { public class Serializer { public Serializer() { } /// /// Method to deserialise an object from a string of hex characters /// /// /// the object which was deserialised public Object DeserialiseObject(String hex) { System.IO.MemoryStream stream2; System.Runtime.Serialization.Formatters.Binary.BinaryFormatter bformatter2 = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter(); byte[] array = HexStringToByteArray(hex); stream2 = new System.IO.MemoryStream(array); Object obj = bformatter2.Deserialize(stream2); stream2.Close(); return obj; } /// /// Method to serialise an object into a hex string /// /// /// public string serializeObject(Object temp) { //write it to stream System.IO.MemoryStream stream2 = new System.IO.MemoryStream(); System.Runtime.Serialization.Formatters.Binary.BinaryFormatter bformatter2 = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter(); bformatter2.Serialize(stream2, temp); byte[] array = new byte[stream2.Length]; array = stream2.ToArray(); String hex = ByteArrayToHexString(array); stream2.Close(); return hex; } /// /// Helper to change a byte array to a hex string /// /// /// string of hex characters private static string ByteArrayToHexString(byte[] Bytes) { StringBuilder Result; string HexAlphabet = "0123456789ABCDEF"; Result = new StringBuilder(); foreach (byte B in Bytes) { Result.Append(HexAlphabet[(int)(B >> 4)]); Result.Append(HexAlphabet[(int)(B & 0xF)]); } return Result.ToString();

            B 1 Reply Last reply
            0
            • B BASONJS

              I have done as you suggested and am still getting the same error. The problem now I believe is the way I am serialising the object. I have made a custom class for this: using System; using System.Text; namespace Helper { public class Serializer { public Serializer() { } /// /// Method to deserialise an object from a string of hex characters /// /// /// the object which was deserialised public Object DeserialiseObject(String hex) { System.IO.MemoryStream stream2; System.Runtime.Serialization.Formatters.Binary.BinaryFormatter bformatter2 = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter(); byte[] array = HexStringToByteArray(hex); stream2 = new System.IO.MemoryStream(array); Object obj = bformatter2.Deserialize(stream2); stream2.Close(); return obj; } /// /// Method to serialise an object into a hex string /// /// /// public string serializeObject(Object temp) { //write it to stream System.IO.MemoryStream stream2 = new System.IO.MemoryStream(); System.Runtime.Serialization.Formatters.Binary.BinaryFormatter bformatter2 = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter(); bformatter2.Serialize(stream2, temp); byte[] array = new byte[stream2.Length]; array = stream2.ToArray(); String hex = ByteArrayToHexString(array); stream2.Close(); return hex; } /// /// Helper to change a byte array to a hex string /// /// /// string of hex characters private static string ByteArrayToHexString(byte[] Bytes) { StringBuilder Result; string HexAlphabet = "0123456789ABCDEF"; Result = new StringBuilder(); foreach (byte B in Bytes) { Result.Append(HexAlphabet[(int)(B >> 4)]); Result.Append(HexAlphabet[(int)(B & 0xF)]); } return Result.ToString();

              B Offline
              B Offline
              BASONJS
              wrote on last edited by
              #6

              I have got to this point. The classes are all now in this format:

              using System;
              using System.Collections;
              using System.Xml.Serialization;
              using System.Xml;

              namespace Data.Package
              {
              [System.Xml.Serialization.XmlTypeAttribute(Namespace = "Data.Package", TypeName = "Changes")]
              public class Changes
              {
              private Boolean blnIsDirty;
              private Boolean blnIsNew;

                  public Changes() 
                  {
                      this.blnIsDirty = false;
                      this.blnIsNew = true;
                  }
              
                  \[System.Xml.Serialization.XmlElementAttribute(ElementName = "IsDirty")\]
                  public Boolean IsDirty
                  {
                      get { return blnIsDirty; }
              
                      set { blnIsDirty = value; }
                  }
              
                  \[System.Xml.Serialization.XmlElementAttribute(ElementName = "IsNew")\]
                  public Boolean IsNew
                  {
                      get { return blnIsNew; }
              
                      set { blnIsNew = value; }
                  }
              }
              

              }

              My serialization class is as follows:

              using System;
              using System.Text;
              using System.Xml.Serialization;
              using System.IO;
              using System.Xml;

              namespace Helper
              {
              public class Serializer
              {
              public Serializer()
              {

                  }
              
                  /// /// Method to convert a custom Object to XML string
                  /// 
                  /// Object that is to be serialized to XML
                  /// XML string
                  public String serializeObject(Object pObject)
                  {
                      try
                      {
                          String XmlizedString = null;
                          MemoryStream memoryStream = new MemoryStream();
                          XmlSerializer xs = new XmlSerializer(pObject.GetType());
                          XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, Encoding.UTF8);
                          xs.Serialize(xmlTextWriter, pObject);
                          memoryStream = (MemoryStream)xmlTextWriter.BaseStream;
                          XmlizedString = UTF8ByteArrayToString(memoryStream.ToArray());
                          return XmlizedString;
                      }
                      catch (Exception e)
                      {
                          System.Console.WriteLine(e);
                          return null;
                      }
                  } 
                  
                  /// /// Method to reconstruct an Object from XML string
                  /// 
                  /// 
                  /// 
                  public Object deserializeObject(String pXmlizedString)
                  {
              
              1 Reply Last reply
              0
              Reply
              • Reply as topic
              Log in to reply
              • Oldest to Newest
              • Newest to Oldest
              • Most Votes


              • Login

              • Don't have an account? Register

              • Login or register to search.
              • First post
                Last post
              0
              • Categories
              • Recent
              • Tags
              • Popular
              • World
              • Users
              • Groups