Question

possibly a duplicate of this question

I'm trying to serialize a set of objects using the standard DataSerializer which is used with wcf.

object structure:

[KnownType(typeof(PersonnelClassProperty))]
[KnownType(typeof(ResourceClassProperty))]
[KnownType(typeof(Person))]
[KnownType(typeof(PersonProperty))]
[KnownType(typeof(ResourceDefinitionProperty))]
[DataContract]
public class Person: ResourceDefinition
{
   [DataMember]
   public guid id {get; set;}

   [DataMember]
   public IList<PersonProperty> personProperties {get; set;}

   [DataMember]
   public IList<PersonnelClass> personnelClasses {get; set;}
}

PersonProperty : ResourceDefinitionProperty

  • PersonnelClassProperty

PersonnelClass : ResourceClass

  • Persons
  • PersonnelClassProperty

PersonnelClassPoperty : ResourceClassProperty

The Above structure is mapped using Nhibernate. so the Base classes are abstract classes with base properties which we override into the main classes. we are using this so we can use a generic class for calling the CRUD functions in Nhibernate.

the first problem this poses is a circular reference, we fixed this. by resetting the lists of the objects we eliminated a circular reference problem.

we also loop through the properties and the associated class properties to get them, as they are being lazily loaded through nHibernate

this allowed me to generate some test data. we now have one personnelclass with a personnelclassproperty. these are being retrieved fine on its own. next we have a person. we added a reference to the personnelclass, and a personnelclassproperty. in the database we have an extra table that holds the reference for the link between the person and personnelclass, as this a many-to-many relationShip. the personProperty has a reference to a single personnelClassproperty, so a FK suffices here.

here, we run into the second problem, a serialization exception occurs:

'PersonnelClassPropertyProxy' with data contract name 'PersonnelClassPropertyProxy:http://schemas.datacontract.org/2004/07/' is not expected. Consider using a DataContractResolver or add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer.

so taken from the question mentioned in the first line i proceeded to add the [DataContract], [DataMember] and [KnownType(typeof(T))] attributes to the classes mentioned above. where T is of course the correct type.

what happens is that we send person objects through wcf to a receiving party, which works fine if the is no link between the personProperty and the personnelClassProperty, but if we add a personproperty with a link to PersonnelClassProperty, we get the exception mentioned above.

all the examples and questions i see online work the same way

so concretely; what am i doing wrong? or what am i forgetting here?

i'll try to update the question with more code to illustrate the objects we use.

edit: I updated the structure of the Person object to show what i have done with the KnownTypes. note that this also holds the personnelClassProperty type, i have also did this for the PersonProperty object, because that is the actual class that holds the PersonnelClassProperty object, but a list of personProperties is used in Person. this doesn't work either.

Was it helpful?

Solution

i found the solution. Because we are using NHibernate, we are lazy loading the personnelClassProperty into the Personproperty and eventually into the Person. this results into the serialization exception.

there are actually 2 solutions to solve the exception:

1: you can set the Not.LazyLoad() property instead of LazyLoad() at the mapping of the object to NHibernate

2: you can leave the Lazyload() property enabled and instead take an item from the object and do something with it before you try to serialize it. It is not enough to create a new variable like so:

PersonnelClassProperty classproperty = personProperty.PersonnelClassProperty;

you really have to do something with an internal object, like so:

PersonnelClassProperty classProperty = personProperty.PersonnelClassProperty;
System.Diagnostics.Debug.WriteLine(classproperty.Dbid);

we opted currently to use the .Not.Lazyload() option

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top