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

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 avail. I have officially run out of ideas and would greatly appreciate anyone who has experience or ideas regarding this problem.

Thank you very much in advance for your time and excuse the length of the post.

Comments

  • Ok - so this is a good question -

    I see that you tried using the XmlInclude attribute, but weren't sure you were using it properly. This is actually the solution to your problem so let me go over where and how to use this attribute:

    First - XmlInclude and SoapInclude are used for different types of serialization. So if XmlInclude isn't working - try replacing it with SoapInclude, and this may solve your problem.

    The problem that is occuring is that you have a base class specified on your wrapper class - but are passing an inheritor. So when the serialization gets to this property it doesn't know what to do with the extra data.

    of course you would think that logically it should just record just the data specified by the base type, but it becomes frightened when unsure and just throws an exception instead.

    What you need to do is slap that attribute - one per inheriting class - on to the declaration of the base class. Check out the example below...

    [code]
    [XmlInclude(typeof(InheritA))]
    [XmlInclude(typeof(InheritB))]
    [XmlInclude(typeof(InheritC))]
    public class BaseClass
    {
    public string Name { get; set; }
    }

    public class InheritA : BaseClass
    {
    public InheritA()
    {
    Name = "InheritA";
    }

    public int Value { get { return 1; } }
    }

    public class InheritB : BaseClass
    {
    public InheritB()
    {
    Name = "InheritB";
    }

    public int Value { get { return 2; } }
    }

    public class InheritC : BaseClass
    {
    public InheritC()
    {
    Name = "InheritC";
    }

    public int Value { get { return 3; } }
    }


    public class Wrapper
    {
    public BaseClass Item { get; set; }
    }
    [/code]

    now, like I said before - depending on the type of serialization that is going on you may want to replace all of the XmlInclude attributes with SoapInclude attributes.

    This should solve the issue.
    For a quick test, run the following code...
    [code]
    var xmls = new XmlSerializer(typeof (Wrapper));
    var stream = File.Create("C:\test.txt");
    var item = new Wrapper() {Item = new InheritB()};
    xmls.Serialize(stream, item);
    stream.Close();
    stream.Dispose();
    [/code]

    You should now have a file on your c drive containing the serialized data.

    ><//~Psightoplasm`~
Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Categories

In this Discussion