Protobuf type inheritance with WCF - wcf

We have trouble with the protobuf-net type inheritance.
We have a base class like this:
[DataContract, ProtoContract]
public abstract class BaseClass : IBase
{
protected IBase()
{
RequestUID = Guid.NewGuid();
}
[DataMember(Order = 8000), ProtoMember(8000)]
public Guid ID { get; set; }
[DataMember(Order = 8001), ProtoMember(8001)]
public string User { get; set; }
}
And classes which inherits from BaseClass.
[DataContract, ProtoContract]
public class ConcreteClass : BaseClass
{
[DataMember(Order = 4), ProtoMember(4)]
public int? WorkItemId { get; set; }
}
(In future we are going to use only ProtoMember and ProtoContract.)
When the client and server starts we do following in both environments:
RuntimeTypeModel.Default[typeof(BaseClass)].AddSubType(50, typeof(ConcreteClass));
Now when we pass an instance of ConcreteClass to a WCF service operation we get exceptions:
BaseClass does not provide a public constructor. (Wrong type chosen for deserialization)
Or if we provide a public constructor for BaseClass it tries to cast the BaseClass object to ConcreteClass on the server. (Again wrong type)
And under some special circumstances (we don't know exactly when this happens) Protobuf tries to deserialize from OtherConcreteClass to ConcreteClass.
What are we doing wrong? The WCF behavior is register correctly. We had no problems with simple classes (no inheritance).
Is there and documentation how two configure the inheritance properly for WCF scenarios?
Thanks

Related

serialize an interface wcf

I have an interface, called IDeviceConfig, as follows:
[KnownType(typeof(Device))]
[KnownType(typeof(DeviceGroup))]
[DataContract()]
public interface IDeviceConfig
{
[DataMember()]
string Name { get; set; }
[DataMember()]
List<Property> Properties { get; set; }
ActionResult PerformAction(string ActionId);
}
The interface will be implemented by two classes, as follows:
public class Device : IDeviceConfig
{
...
}
public class DeviceGroup : IDeviceConfig
{
...
}
In my WCF service, I need to return a list of IDeviceConfigs; when I decorate the interface with KnownType, Visual studio complains saying that Attribute 'KnownType' is not valid on this declaration type.
Can someone please explain how to return a list of IDeviceconfigs?
If you look at the definition of KnownTypeAttribute, you cannot apply to Interfaces.
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, Inherited = true, AllowMultiple = true)]
public sealed class KnownTypeAttribute : Attribute
"Known types can be associated only with classes and structures, not interfaces." from here:
http://msdn.microsoft.com/en-us/library/ms730167.aspx

Common WCF Response Handler?

I have a WCF Client, and the Endpoint has just been upgraded with a new method (OperationContract). I want to write a common method to handle the response from this new method as well as from the existing method at the endpoint.
I am trying to create a "Base" response class and adding common properties to it provided by the WCF endpoint, but I notice in my handler method, the properties are not being retained.
The code for the class I want all responses to inherit from looks like this :
public class ResponseBase
{
public string[] ItemsReturned;
public bool ItemsWereAvailable;
}
So I add partial declarations to get this onto the objects in the endpoint.
public partial class RetrieveResponse :ResponseBase
{
}
public partial class RetrieveResponse2 :ResponseBase
{
}
This way I have a handler method that just accepts "ResponseBase" as its input.
Am I doing this all wrong?
Any class whose instances will be return values and/or parameters of an operation contract should be decorated with the DataContract attribute, and the properties, as DataMembers:
[DataContract]
public class ResponseBase
{
[DataMember]
public string[] ItemsReturned { get; set; }
[DataMember]
public bool ItemsWereAvailable { get; set; }
}
http://msdn.microsoft.com/en-us/library/ms733127.aspx
If they are not, the DataContractSerializer doesn't serialize them.

Expose WCF service for derived class with same name in C#

I want to expose as WCF service two set of classes that have the same name. However, when I add the service reference, it only returns one set of the class.
[ServiceContract(Name = "Service1")]
[XmlSerializerFormat]
public interface IService1
{
[OperationContract]
[ServiceKnownType(typeof(S1.Retangle))]
[ServiceKnownType(typeof(S1.Square))]
[ServiceKnownType(typeof(S2.Retangle))]
[ServiceKnownType(typeof(S2.Square))]
string GetShape(Shape shape);
}
//All types are only example
[System.SerializableAttribute()]
[System.Xml.Serialization.XmlTypeAttribute()]
public abstract class Shape
{
public int Width { get; set; }
public int Height { get; set; }
public string TypeName { get; set; }
}
namespace S1
{
[System.SerializableAttribute()]
[System.Xml.Serialization.XmlTypeAttribute()]
public class Retangle : Shape
{ }
[System.SerializableAttribute()]
[System.Xml.Serialization.XmlTypeAttribute()]
public class Square : Shape
{ }
}
namespace S2
{
//[DataContract]
[System.SerializableAttribute()]
[System.Xml.Serialization.XmlTypeAttribute(Namespace = "Namespace=http://tempuri.org/S2")] //can be changed
public class Retangle : Shape
{ }
//[DataContract]
[System.SerializableAttribute()]
[System.Xml.Serialization.XmlTypeAttribute(Namespace = "Namespace=http://tempuri.org/S2")] //can be changed
public class Square : Shape
{ }
}
Any idea would be very much appreciated.
WCF will generate your objects in its own namespace for use client side but your not forced to use these - you can equally well use your own original objects in the namespaces they were defined by either:
1. Compiling them in a dll and linking to that for both client and sever.
2. If you dont want overhead of shared dll just compile them directly into both server and client.
In the generated proxy code you just need to replace the WCF namespace tags with your own org namespaces so they resolve to your objects and the client side WCF generated ones are ignored.

DataContract composite Class

I have a problem with serialization composite class (using WCF Service).
here my class in namespace1 (it is not in service namespace) :
[DataContract]
public class UpData
{
[DataMember]
public double Version ;
public UpData()
{
this.Version = -1;
}
}
In my Service namespace (in interface) I deсlare this procedure :
ArrayList GetDownloadPath(Dictionary<string,string> lib1, Dictionary<string,string> lib2);
ArrayList contains UpData objects.
I have error(
How will be right to send ArrayList of UpData objects? (may be specific DataContract?)
Thanks a lot!
I'm not sure if ArrayList is serializable by default. Using a generic list could solve your problem:
[OperationContract]
List<UpData> GetDownloadPath(Dictionary<string,string> lib1, Dictionary<string,string> lib2);
EDIT: I think you also need to specify a getter and setter for your Version property, i.e.
[DataContract]
public class UpData
{
[DataMember]
public double Version { get; set; }
public UpData()
{
this.Version = -1;
}
}
More info here.

How can I pass a List<Interface> over WCF?

I have a WCF service where I am trying to return a List (where IWatchable is a custom interface I have built) in one of my operation contracts. When I test the service on the client the method returns an object[] instead of List<IWatchable>. Is it possible to return a List of IWatchable, since IWatchable is an interface with WCF?
Method:
public List<IWatchable> GetWorkload( Guid nodeId, int maximum )
IWatchable:
public interface IWatchable
{
string ActionName { get; set; }
Guid ActionReference { get; set; }
}
Hopefully a bit more info will be helpful...
I have a derived interface:
public interface IAMRAWatchable: IWatchable
And three concrete implementations from IAMRAWatchable:
public class InstrumentationWatch: IAMRAWatchable
public class OutputWatch: IAMRAWatchable
etc...
In my WCF method that returns List<IWatchable> I want to send an InstrumentationWatch and an OutputWatch to the client... Is this possible or am I going about this the wrong way?
Resolved
Thanks to John I found my solution. KnownType wasn't working since I was using List<IWatchable> - So I wrapped my list into a new class and added the attributes to it. I'll need to re-factor my code but for others who are interested here is the class:
[DataContract]
[KnownType( typeof( InstrumentationWatch ) )]
[KnownType( typeof( OutputWatch ) )]
public class WorkInfo
{
[DataMember]
public List<IWatchable> WorkQueue { get; set; }
}
and my WCF method:
public WorkInfo GetWorkload( Guid nodeId, int maximum )
An interface can never be serialized. It is only a description of behavior.
You can serialize objects which implement the interface, but you must tell WCF what their types are. See Data Contract Known Types.