Returning recursive structure from WCF service - wcf

I have below data structure to represent the tree
public class TreeNode : IEnumerable<TreeNode>
{
private readonly Dictionary<string, TreeNode> _children =
new Dictionary<string, TreeNode>();
public readonly string ID;
public TreeNode Parent { get; private set; }
public TreeNode()
{
this.ID = Guid.NewGuid().ToString();
}
public void AddChild(TreeNode tNode)
{
if (tNode.Parent != null)
{
tNode.Parent._children.Remove(tNode.ID);
}
tNode.Parent = this;
this._children.Add(tNode.ID, tNode);
}
public IEnumerator<TreeNode> GetEnumerator()
{
return this._children.Values.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
}
I am trying to return this tree structure from wcf service.
[OperationContract]
TreeNode GetMenuItems();
and i get exception saying "Type 'TreeNode' is a recursive collection data contract which is not supported. Consider modifying the definition of collection 'TreeNode' to remove references to itself."
When i annotated the TreeNode calss with [DataContract(IsReference = true)], exception went away.
But when the treenode is received in the client side its children _children property is not coming populated and its always null.
Thanks,
Mallikarjun

By annotating _children with DataMember issue got resolved.

Related

Json Serialize an interface's properties which have non primitive types [duplicate]

With a simple class/interface like this
public interface IThing
{
string Name { get; set; }
}
public class Thing : IThing
{
public int Id { get; set; }
public string Name { get; set; }
}
How can I get the JSON string with only the "Name" property (only the properties of the underlying interface) ?
Actually, when i make that :
var serialized = JsonConvert.SerializeObject((IThing)theObjToSerialize, Formatting.Indented);
Console.WriteLine(serialized);
I get the full object as JSON (Id + Name);
The method I use,
public class InterfaceContractResolver : DefaultContractResolver
{
private readonly Type _InterfaceType;
public InterfaceContractResolver (Type InterfaceType)
{
_InterfaceType = InterfaceType;
}
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
//IList<JsonProperty> properties = base.CreateProperties(type, memberSerialization);
IList<JsonProperty> properties = base.CreateProperties(_InterfaceType, memberSerialization);
return properties;
}
}
// To serialize do this:
var settings = new JsonSerializerSettings() {
ContractResolver = new InterfaceContractResolver (typeof(IThing))
};
string json = JsonConvert.SerializeObject(theObjToSerialize, settings);
Improved version with nested interfaces + support for xsd.exe objects
Yet another variation here. The code came from http://www.tomdupont.net/2015/09/how-to-only-serialize-interface.html with the following improvements over other answers here
Handles hierarchy, so if you have an Interface2[] within an Interface1 then it will get serialized.
I was trying to serialize a WCF proxy object and the resultant JSON came up as {}. Turned out all properties were set to Ignore=true so I had to add a loop to set them all to not being ignored.
public class InterfaceContractResolver : DefaultContractResolver
{
private readonly Type[] _interfaceTypes;
private readonly ConcurrentDictionary<Type, Type> _typeToSerializeMap;
public InterfaceContractResolver(params Type[] interfaceTypes)
{
_interfaceTypes = interfaceTypes;
_typeToSerializeMap = new ConcurrentDictionary<Type, Type>();
}
protected override IList<JsonProperty> CreateProperties(
Type type,
MemberSerialization memberSerialization)
{
var typeToSerialize = _typeToSerializeMap.GetOrAdd(
type,
t => _interfaceTypes.FirstOrDefault(
it => it.IsAssignableFrom(t)) ?? t);
var props = base.CreateProperties(typeToSerialize, memberSerialization);
// mark all props as not ignored
foreach (var prop in props)
{
prop.Ignored = false;
}
return props;
}
}
Inspired by #user3161686, here's a small modification to InterfaceContractResolver:
public class InterfaceContractResolver<TInterface> : DefaultContractResolver where TInterface : class
{
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
IList<JsonProperty> properties = base.CreateProperties(typeof(TInterface), memberSerialization);
return properties;
}
}
You can use conditional serialization. Take a look at this link. Basicly, you need to implement the IContractResolver interface, overload the ShouldSerialize method and pass your resolver to the constructor of the Json Serializer.
An alternative to [JsonIgnore] are the [DataContract] and [DataMember] attributes. If you class is tagged with [DataContract] the serializer will only process properties tagged with the [DataMember] attribute (JsonIgnore is an "opt-out" model while DataContract is "op-in").
[DataContract]
public class Thing : IThing
{
[DataMember]
public int Id { get; set; }
public string Name { get; set; }
}
The limitation of both approaches is that they must be implemented in the class, you cannot add them to the interface definition.
You can add the [JsonIgnore] annotation to ignore an attribute.
I'd like to share what we ended up doing when confronted with this task. Given the OP's interface and class...
public interface IThing
{
string Name { get; set; }
}
public class Thing : IThing
{
public int Id { get; set; }
public string Name { get; set; }
}
...we created a class that is the direct implementation of the interface...
public class DirectThing : IThing
{
public string Name { get; set; }
}
Then simply serialized our Thing instance, deserialized it as a DirectThing, then Serialized it as a DirectThing:
var thing = new Thing();
JsonConvert.SerializeObject(
JsonConvert.DeserializeObject<DirectThing>(JsonConvert.SerializeObject(thing)));
This approach can work with a long interface inheritance chain...you just need to make a direct class (DirectThing in this example) at the level of interest. No need to worry about reflection or attributes.
From a maintenance perspective, the DirectThing class is easy to maintain if you add members to IThing because the compiler will give errors if you haven't also put them in DirectThing. However, if you remove a member X from IThing and put it in Thing instead, then you'll have to remember to remove it from DirectThing or else X would be in the end result.
From a performance perspective there are three (de)serialization operations happening here instead of one, so depending on your situation you might like to evaluate the performance difference of reflector/attribute-based solutions versus this solution. In my case I was just doing this on a small scale, so I wasn't concerned about potential losses of some micro/milliseconds.
Hope that helps someone!
in addition to the answer given by #monrow you can use the default [DataContract] and [DataMember]
have a look at this
http://james.newtonking.com/archive/2009/10/23/efficient-json-with-json-net-reducing-serialized-json-size.aspx
Finally I got when it will not work...
If you want to have inside another complex object it will not be properly serialized.
So I have made version which will extract only data stored in specific assembly and for types which have the same base interface.
So it is made as .Net Core JsonContractResolver.
In addition to data extraction it solves:
a) camelCase conversion before sending data to client
b) uses top most interface from allowed scope (by assembly)
c) fixes order of fields: field from most base class will be listed first and nested object will meet this rule as well.
public class OutputJsonResolver : DefaultContractResolver
{
#region Static Members
private static readonly object syncTargets = new object();
private static readonly Dictionary<Type, IList<JsonProperty>> Targets = new Dictionary<Type, IList<JsonProperty>>();
private static readonly Assembly CommonAssembly = typeof(ICommon).Assembly;
#endregion
#region Override Members
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
if (type.Assembly != OutputJsonResolver.CommonAssembly)
return base.CreateProperties(type, memberSerialization);
IList<JsonProperty> properties;
if (OutputJsonResolver.Targets.TryGetValue(type, out properties) == false)
{
lock (OutputJsonResolver.syncTargets)
{
if (OutputJsonResolver.Targets.ContainsKey(type) == false)
{
properties = this.CreateCustomProperties(type, memberSerialization);
OutputJsonResolver.Targets[type] = properties;
}
}
}
return properties;
}
protected override string ResolvePropertyName(string propertyName)
{
return propertyName.ToCase(Casing.Camel);
}
#endregion
#region Assistants
private IList<JsonProperty> CreateCustomProperties(Type type, MemberSerialization memberSerialization)
{
// Hierarchy
IReadOnlyList<Type> types = this.GetTypes(type);
// Head
Type head = types.OrderByDescending(item => item.GetInterfaces().Length).FirstOrDefault();
// Sources
IList<JsonProperty> sources = base.CreateProperties(head, memberSerialization);
// Targets
IList<JsonProperty> targets = new List<JsonProperty>(sources.Count);
// Repository
IReadOnlyDistribution<Type, JsonProperty> repository = sources.ToDistribution(item => item.DeclaringType);
foreach (Type current in types.Reverse())
{
IReadOnlyPage<JsonProperty> page;
if (repository.TryGetValue(current, out page) == true)
targets.AddRange(page);
}
return targets;
}
private IReadOnlyList<Type> GetTypes(Type type)
{
List<Type> types = new List<Type>();
if (type.IsInterface == true)
types.Add(type);
types.AddRange(type.GetInterfaces());
return types;
}
#endregion
}

JAXB: serialize private fields and deserialize without a parameter-less contructor

The problem I have involves a pretty complex class structure but I managed to summarize the gist of it in the following simpler example. I need to be able to serialize an object of class MyItem (including private property 'text') and subsequently deserialize it without having a parameter-less constructor available and without being able to create one because it would totally mess up the current logic.
class MyCollection:
#XmlRootElement(name="collection")
public class MyCollection {
public MyCollection() {
this.items = new ArrayList<MyItem>();
}
#XmlElement(name="item")
private List<MyItem> items;
public void addItem(String text) {
this.items.add(new MyItem(text));
}
}
class MyItem:
public class MyItem {
public MyItem(String text) {
this.text = text;
}
#XmlAttribute
private String text;
}
The first requirement (serialize MyItem including private property) is met out of the box and I get the following xml as a result:
<collection>
<item text="FIRST"/>
<item text="SECOND"/>
<item text="THIRD"/>
</collection>
In order to meet the second requirement I decorated class MyItem with attribute #XmlJavaTypeAdapter
#XmlJavaTypeAdapter(MyItemAdapter.class)
public class MyItem {
...
and introduced classes AdaptedMyItem
public class AdaptedMyItem {
private String text;
public void setText(String text) { this.text = text; }
#XmlAttribute
public String getText() { return this.text; }
}
and MyItemAdapter
public class MyItemAdapter extends XmlAdapter<AdaptedMyItem, MyItem> {
#Override
public MyItem unmarshal(AdaptedMyItem adaptedMyItem) throws Exception {
return new MyItem(adaptedMyItem.getText());
}
#Override
public AdaptedMyItem marshal(MyItem item) throws Exception {
AdaptedMyItem result = new AdaptedMyItem();
result.setText("???"); // CANNOT USE item.getText()
return result;
}
}
but this is where I get stuck because in method marshal I cannot access MyItem.text and so I cannot use the standard approach for dealing with immutable classes in JAXB.
Bottomline: I would like to use the class adapter mechanism only when deserializing (because I need to invoke a non-parameterless constructor) but not when serializing (because I cannot access private properties). Would that be possible?

Trouble with DataContractSerializer

I'm trying to make DataContract Serializer work with one of my class.
Here it is :
public class MyOwnObservableCollection<T> : ObservableCollection<T>, IDisposable
where T : IObjectWithChangeTracker, INotifyPropertyChanged
{
protected List<T> removedItems;
[DataMember]
public List<T> RemovedItems
{
get { return this.removedItems;}
set { this.removedItems = value;}
}
// Other code removed for simplification
// ...
//
}
It is important to understand that the RemovedItems list gets populated automatically when you remove an Item from the ObservableCollection.
Now serializing an instance of this class using the DataContractSerializer with one element in the removedItems list with the following code :
MyOwnObservableCollection<Test> _Test = new MyOwnObservableCollection<Test>();
DataContractSerializer dcs = new DataContractSerializer(typeof(MyOwnObservableCollection<Test>));
XmlWriterSettings settings = new XmlWriterSettings() { Indent = true };
string fileName = #"Test.xml";
Insurance atest = new Test();
atest.Name = #"sfdsfsdfsff";
_Test.Add(atest);
_Test.RemoveAt(0); // The Iitem in the ObservableCollection is moved to the RemovedItems List/
using (var w = XmlWriter.Create(fileName, settings))
{
dcs.WriteObject(w, _Test);
}
ends with nothing in the XML file :
<?xml version="1.0" encoding="utf-8"?>
<ArrayOfTest xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="MyNameSpace" />
Why is this public property ignored ? What have I missed here ?
TIA.
The problem here is that your class is derived from a collection, and as such, the DataContractSerializer serializes only its items, but not any extra properties, as stated here: No properties when using CollectionDataContract.
A workaround would be using the original (inherited) collection as a property, rather than inheriting from it:
public class MyOwnObservableCollection<T> : IDisposable
where T : IObjectWithChangeTracker, INotifyPropertyChanged
{
readonly ObservableCollection<T> originalCollection = new ObservableCollection<T>();
protected List<T> removedItems = = new List<T>();
[DataMember]
public List<T> RemovedItems
{
get { return this.removedItems;}
set { this.removedItems = value;}
}
[DataMember]
public ObservableCollection<T> OriginalCollection
{
get { return this.originalCollection; }
}
// ...
}

Using a datamember type of list

i'm new with wcf and i create a DataContract like this :
[DataContract]
public class directoriesUser
{
[DataMember]
public string NameDir { get; set; }
[DataMember]
public directoriesUser Parent { get; set; }
private ObservableCollection<directoriesUser> _userDirs = new ObservableCollection<directoriesUser>();
[DataMember]
public ObservableCollection<directoriesUser> UserDirectories
{
get { return _userDirs; }
set { _userDirs = value; }
}
}
But whe i use this class like above, the service throw an exception. can someone help me ?
public directoriesUser getHomeUser(int user_id)
{
directoriesUser dirhome = new directoriesUser();
// this doesn't works
dirhome.UserDirectories = new ObservableCollection<directoriesUser>{
new directoriesUser { NameDir = "dir1", Parent = dirhome},
new directoriesUser {NameDir = "dir2", Parent = dirhome}
};
// neither this one
dirhome.UserDirectories.Add(new directoriesUser {NameDir = "dir3", Parent = dirhome})
return dirhome;
}
Your directoriesUser class probably causes recursion when wcf serializes the instance. This is basically caused by the Parent property pointing back up the hierarchy.
Here's a more detailed article about this.

wcf generic datacontract does not get serialized

I am having the following data structure:
[DataContract]
public class OperationResult<T>
{
public OperationResult() { }
[DataMember]
public Int32 OpResult
{
get;set;
}
[DataMember]
public IList<T> OperationResults
{
get;set;
}
public static OperationResult<T> Success(IList<T> results, int numberOfChangedObjects)
{
OperationResult<T> result = new OperationResult<T>();
result.OpResult = 1;
result.OperationResults = results;
return result;
}
}
When I update the service reference, the class does not get serialized. In the service I am using a so-called closed generic type
eg.
[OperationContract]
public OperationResult<Int32> SometTestMethod()
{
return new OperationResult<Int32>
{
OpResult = 1,
OperationResults = new List<Int32> {1, 2, 3}
};
}
The method is exposed, but the return type OperationResult in this case is not accesible.
What am I doing wrog?
Thanks
I just realized. The reason I didn't find the type is because I was looking for an OperationResult. As it got serialized , it was named OperationResultOfInt.