Using protobuf-net with inheritance and interface - c#

I have a proto contract as follows:
[ProtoContract]
public MyContract: ContractBase
{
[ProtoMember(1)]
List<IMyDto> MyData
{
get;
set;
}
}
My IMyDto looks like this and its implemenation MyDto
[ProtoInclude(600, typeof(MyDto))]
public interface IMyDto
{
int MyData
{
get;
set;
}
}
[ProtoContract]
public class MyDto :IMyDto
{
[ProtoMember(1)]
int MyData
{
get;
set;
}
}
Finally, my ContractBase looks like this:
[ProtoContract]
[ProtoInclude(500, typeof(MyContract))]
public class ContractBase
{
[ProtoMember(501)]
public string[] ErrorMessages
{
get;
set;
}
}
When I make the web service call, I keep getting the following error:
It was not possible to prepare a serializer for: ContractBase ---> System.InvalidOperationException: No serializer defined for type: IMyDto
Please note that this is a simplified version of code for understanding the problem.
Please let me know what I'm doing wrong?
Any help is much appreciated.
Thanks.

Mark IMyDto with [ProtoContract] attribute.
It worked for me, after I've done that.
Getting Started documentation says, it is necessary every type participating in serialization is marked so.

Related

WCF service method unavailable in WCF Test Client because it uses type SampleClass

I have looked for many solutions but could not find any satisfactory answer.
I have 2 classes:
[DataContract]
public class SampleClass
{
[DataMember]
public PerformanceCounters Performance { get; set; }
}
[DataContract]
public class PerformanceCounters
{
[DataMember]
public double ExecutionTime { get; set; }
[DataMember]
public int ResultsCount { get; set; }
}
My OperationContract is ->
public SampleClass GetResult ()
{
return new SampleClass();
}
On adding this to wcfTestClient , I get the this error with red cross: "WCF service method unavailable in WCF Test Client because it uses type SampleClass"
If I replace PerformanceCounters object in SampleClass with standard data types such as int, string then it works perfectly.
I have already looked around enough but still have not got any resolution.

Using Datacontract: WCF

How should i be declaring the datacontracts
My Operation contract has a Method:
Apple GetApples()
My data Contract Apple looks Like
[DataContract]
public class Apple
{
[DataMember]
public int Id { get; set; }
[DataMember]
public FruitType type { get; set; }
}
As there is another member of type FruitType.
[DataContract]
public class FruitType
{
[DataMember]
public int Id { get; set; }
[DataMember]
public string type { get; set; }
}
OR
as a simple class
public class FruitType
{
public int Id { get; set; }
public string type { get; set; }
}
What is the difference between these two? other than that the simple type is not a datacontract and will depende on how i want to use it.?
how should i declare it??
Those attributes give you the control over how your properties will be represented in different formats. For example for XML you can specify the XML Namespace and XML node names.
Even if you are happy with default property names and default namespace, when you try to serialize data to XML, your XML nodes will have weird names such as typek_BackingField.
In other words, if you use WCF you should use DataContract and DataMember attributes, even if you think it works fine the formatted data may not look what you expect. As a result it removes compatibility with other (non-WCF) systems. Or even when you don't share your types (contracts) with other WCF systems.

Issue porting to Mono: Failed to convert parameters due to namespace issue during deserialization

On Windows, with .NET. There is no issue serializing or deserializing the following WCF web object:
[DataContract]
public class Payload
{
public Payload() {}
public class SubPayloadOne
{
public String Name { get; set; }
public int Count { get; set; }
}
public class SubPayloadTwo
{
public String Name { get; set; }
public int Number { get; set; }
}
[DataMember]
public SubPayloadOne P1 { get; set; }
[DataMember]
public SubPayloadTwo P2 { get; set; }
}
On Mono (on Ubuntu), attempting to deserialize the web object in the example above will result in the following error: System.InvalidOperationException: Failed to set value of type String[Payload+SubPayloadOne+Name] for property String[Payload+SubPayloadTwo+Name] String ---> System.ArgumentException: failed to convert parameters
My theory is that Mono is not including the full namespace when deserializing the object. In other words, it is confusing Payload.SubPayloadTwo.Name for Payload.SubPayloadOne.Name, because both objects are "Name" if you do not consider their full namespace.
Following through on the theory above, I tried resolving this problem by renaming Payload.SubPayloadOne.Name or Payload.SubPayloadTwo.Name to something else, for example, Payload.SubPayloadTwo.NameTwo. Which did work. However, this would break reverse compatibility with existing product (since existing Payload objects are already in databases).
If at all possible, I'm looking for a solution that does not involve changing the web object. Any thoughts?
Thanks!

Mongodb - entity serialized OK, but gives 'No serializer found for type' error when deserializing

I'm getting this issue using the c# driver for mongodb (v1.5)
I've had similar issues to this when serializing objects, but have always been able to resolve the in the past by registering the entity with mongodb during application startup. The document it's having a problem deserializing is nested two levels deep (ie a document embedded within a document embedded within a document).
The classes look like this:
[BsonIgnoreExtraElements]
public class FooItem : IFooItem
{
[BsonId]
public ObjectId Id { get; set; }
public IFooAccessRestrictions AccessRestrictions { get; set; }
}
public class FooAccessRestrictions : IFooAccessRestrictions
{
[BsonId]
public ObjectId Id { get; set; }
public IAccessPermission[] AccessList { get; set; }
}
public class AccessPermission : IAccessPermission
{
[BsonId]
public ObjectId Id { get; set; }
public DateTimeOffset CreatedOn { get; set; }
public ObjectId CreatedBy { get; set; }
public AccessPermissionType Type { get; set; }
public string PermittedIdentity { get; set; }
public AccessPermission()
{
}
public AccessPermission(ObjectId createdBy, AccessPermissionType type, string permittedIdentity)
{
CreatedOn = DateTime.Now;
CreatedBy = createdBy;
Type = type;
PermittedIdentity = permittedIdentity;
}
}
It's the AccessPermission class that it has the 'No serializer found for type' problem with. I've tried registering the entities with mongodb as follows on application start:
BsonClassMap.RegisterClassMap<FooAccessRestrictions>();
BsonClassMap.RegisterClassMap<AccessPermission>();
I'm guessing I must be breaking some mongodb rule here that I'm not aware of. I hope I don't need to create a custom serializer for this ... As far as I can tell I'm not doing anything I haven't done before, apart from that the document is nested two levels deep. And it is creating the document no problem at all, it's just when I try to get it back out that I have the problem.
Any help would be much appreciated.
Okay, I've managed to fix this now.
After another look at the mongodb documentation, I found out that you can register properties of a class whilst registering the class.
so now my registration looks like this:
BsonClassMap.RegisterClassMap<FooAccessRestrictions>(cm =>
{
cm.MapProperty<List<IAccessPermission>>(c => (List<IAccessPermission>)c.AccessList);
});
(Note that my property has changed from an array to a List, but this shouldn;t have any impact on the issue I'm talking about here)
MongoDB is now able to deserialize these objects as well as serialize them.

Can you use interfaces as DataMembers in WCF?

Can you do this?
[DataContract]
public class RegisterEndpointRequest : NotificationRegistrationServiceRequest
{
[DataMember]
public IEndpoint Endpoint { get; set; }
}
Notice the member Endpoint is an interface (IEndpoint), not a class. Will WCF allow this?
I think you can (but I haven't tested it), but you will then need to declare all implementations of that interface with [KnownType]:
[DataContract]
[KnownType(typeof(EndpointImplA))]
[KnownType(typeof(EndpointImplB))]
public class RegisterEndpointRequest : NotificationRegistrationServiceRequest
{
[DataMember]
public IEndpoint Endpoint { get; set; }
}
Each implementing class must have a [DataContract] attribute.
The DataContractAttribute in WCF is not intended for use on an interface: See the documentation here
The answer in this question may give you a better idea why.
Yes, of course you can have interface as DataMember inside DataContract..
Then you have to have specify all the interface implementations in the KnownType attributes...
[DataContract]
[KnownType(typeof(ActivityDC))]
[KnownType(typeof(StepDC))]
[KnownType(typeof(WaveDC))]
public class CampaignDC : AuditedEntityBaseDC
{
[DataMember]
public IList<IActivityDC> Activities { get; set; }

Categories