WCF not exposing fields but uses ExtensionData - wcf

Im trying to create a WCF which consumes a List
public class myClass {
public int ID { get;set;}
}
In my service i write
[DataContract]
public class myClass
{
public int ID { get; set; }
}
And my client nows the entity
ServiceReference2.myClass[] sendData = new ServiceReference2.myClass[2];
but when i would add a new myClass to the array like
ServiceReference2.myClass add1= new ServiceReference2.myClass();
the entity only exposes the field 'ExtensionData' and not the field ID
What am i doing wrong

You forgot to decorate the ID property with the DataMember attribute:
[DataContract]
public class myClass
{
[DataMember]
public int ID { get; set; }
}

Related

How to set [DataMember] on an autogenerated proxy property

I am working on a wcf webservice. This service uses a third party webservice which I have added as a service reference.
Now I want to publish some properties of this proxyclient to clients who uses my wcfservice, without defining an own class and doing the mapping.
The auto generated code is done as partial class.
public partial class Person : object,
System.ComponentModel.INotifyPropertyChanged
{
public string FirstName;
public string LastName;
...
}
I tried to override these properties by using the MetadataType-Attribute and adding the [DataMember]-Attribute to properties. But this seams to work only for EF.
[DataContract]
[MetadataType(typeof(PersonMetaData))]
public partial class Person
{
[DataMember]
public string FirstName { get; set; }
[DataMember]
public string LastName { get; set; }
}
public class PersonMetaData
{
[DataMember]
public string FirstName { get; set; }
[DataMember]
public string LastName { get; set; }
}
Trying to implement an interface didn't help, the properties are invisible on client.
[DataContract]
public partial class Person : IPerson
{}
public interface IPerson
{
[DataMember]
string FirstName { get; set; }
[DataMember]
string LastName { get; set; }
}
Any idea?
Guido
On my service XmlSerializer failed to serialize the auto-generated class cause of PropertyChanged-event.
If I work with DataContractSerializer and decorate my auto-generated class with [DataContract], I'm not able to decorate the properties by inheritance with [DataMember] because the attibute is not inheritable.
So I extended this partial class by wrapper properties.
[DataContract]
public partial class Person
{
[DataMember]
public string FirstNameWrapper
{
get
{
return this.FirstName;
}
set
{
this.FirstName = value;
}
}
}

WCF with abstract base class with implemented interfaces does not serialize properly?

On the service side I have an abstract base class like so:
[DataContract]
public abstract class EntityBase : IObjectState, IDatabaseMetaData
{
[NotMapped]
[DataMember]
public ObjectState ObjectState { get; set; }
#region IDatabaseMetaData Members
[DataMember] public DateTime InsertDatetime { get; set; }
[DataMember] public int InsertSystemUserId { get; set; }
[DataMember] public DateTime? UpdateDatetime { get; set; }
[DataMember] public int? UpdateSystemUserId { get; set; }
public virtual SystemUser InsertSystemUser { get; set; }
public virtual SystemUser UpdateSystemUser { get; set; }
#endregion
}
Here is an implementing class (data contract):
[DataContract(Namespace = Constants.MyNamespace)]
public class AccountClass : EntityBase
{
[DataMember] public int AccountClassId { get; set; }
[DataMember] public string AccountClassCode { get; set; }
[DataMember] public string AccountClassDesc { get; set; }
}
On the client side I have essentially duplicated contracts. Here is the Client.AccountClass:
public class AccountClass : ObjectBase
{
private int _accountClassId;
private string _accountClassCode;
private string _accountClassDesc;
public int AccountClassId
{
get { return _accountClassId;}
set
{
if (_accountClassId == value) return;
_accountClassId = value;
OnPropertyChanged(() => AccountClassId);
}
}
public string AccountClassCode
{
get { return _accountClassCode; }
set
{
if (_accountClassCode == value) return;
_accountClassCode = value;
OnPropertyChanged(() => AccountClassCode);
}
}
public string AccountClassDesc
{
get { return _accountClassDesc; }
set
{
if (_accountClassDesc == value) return;
_accountClassDesc = value;
OnPropertyChanged(() => AccountClassDesc);
}
}
}
..and here is the parts of ObjectBase that matter:
public abstract class ObjectBase : IObjectState, IDatabaseMetaData
{
public ObjectState ObjectState { get; set; }
#region IDatabaseMetaData Members
public DateTime InsertDatetime { get; set; }
public int InsertSystemUserId { get; set; }
public DateTime? UpdateDatetime { get; set; }
public int? UpdateSystemUserId { get; set; }
#endregion
}
When I debug the service in my WcfMessageInspector.BeforeSendReply, I can see the message correctly sending the IObjectState and IDatabaseMetaData values. However, on the client side, they are always null (or default values). I have tried using KnownTypes, applying the namespace to the abstract class. The only way I can serialize everything correctly is to get rid of the interfaces and base classes all together and put the properties directly on the Client/Server AccountClass object. What am I missing here? Thanks.
Update 1
This seems to be a namespace thing. If I move my EntityBase and ObjectBase into the same CLR Namespace, everything works (with no KnownType attributes). In my client contract's AssemblyInfo.cs file I have this:
[assembly: ContractNamespace(Constants.MyNamespace, ClrNamespace = "Project.Name.Client.Entities")]
I tried adding ContractNamespaces here to no avail. Like I said, unless the EntityBase and ObjectBase are in the same namespace, it won't work. However, this is a problem for me because it creates a circular reference, unless I move a lot of stuff around.
Any idea how I can see what the full data contract (namespaces, DataMembers, etc) looks like just before/after serialization on the client/server? I tried intercepting the OnSerializing event without much luck. Thanks again.
This was a namespace issue.
I explicitly add the correct namespace to all parties involved and everything works great. One thing I notice is that the ContractNamespace's ClrNamespace in your AssemblyInfo.cs file should match the AssemblyTitle. Also, putting more than one ContractNamespace in the AssemblyInfo.cs does nothing. For example, I was doing this:
[assembly: ContractNamespace(Constants.MyNamespace, ClrNamespace = "Company.Project.Client.Entities")]
[assembly: ContractNamespace(Constants.MyNamespace, ClrNamespace = "Company.Project.Client.Entities.Core")]
Any POCO in the Company.Project.Client.Entities.Core would not serialize correctly until I explicitly put the DataContract namespace on it like so
[DataContract(Namespace = Constants.MyNamespace)]
public class SomeObject
{
[DataMember] public string SomeProperty { get; set; }
//..etc
}
Alternatively, I could have restructured the project so SomeObject was in the Company.Project.Client.Entities namespace and that would have worked.
Finally, the most helpful thing to debugging this was looking at the WSDL, and then using a custom IDispatchMessageInspector to see the actual messages AfterReceiveRequest and BeforeSendReply. Hopefully this helps someone.

howto initialize a wcf class

Im trying to use a Class in a WCF service. When im calling the
u.attributeChanges.Add(a);
i get:
"Object reference not set to an instance of an object"
If create the classes in the client application it's working.
UpdateChanges Class
[DataContract]
public class UpdateChanges
{
private void Initialize()
{
this.attributeChanges = new List<AttributeChanges>();
}
public UpdateChanges()
{
this.Initialize();
}
[DataMember]
public string objectGuid { get; set; }
[DataMember]
public Utilities.ObjectTypes objectType { get; set; }
[DataMember]
public Utilities.ChangeType changeType{ get; set; }
[DataMember]
public List<AttributeChanges> attributeChanges { get; set; }
[OnDeserializing]
public void OnDeserializing(StreamingContext ctx)
{
this.Initialize();
}
}
AttributeChanges class
[DataContract]
public class AttributeChanges
{
[DataMember]
public string attributeName { get; set; }
[DataMember]
public string attributeValue { get; set; }
}
Client Code:
Service.DirsyncServiceClient proxyClient;
proxyClient = Utilities.GetProxy("http://192.168.1.45/vDir/Service.svc");
Service.UpdateChanges u = new Service.UpdateChanges();
Service.AttributeChanges a = new Service.AttributeChanges();
a.attributeName = "Attribute1";
a.attributeValue = "Value1";
u.attributeChanges.Add(a);
proxyClient.SaveObject(u);
Anyonw know how to solve this?
You're using a generated client code.
The problem is that the client generates this code on base of the WSDL xlm. The code in the CTOR doesn't generated in the client because the client can't be aware of this code.
You have a few options-
1. Use a shared DLL with the data contract instead of generating it via a web reference.
2. Implement it yourself in a 'partial' class.

Inheritance resolved at runtime in protobuf-net

Is it possible to specify at runtime the sub-types of a specific abstract contract?
In the classic WCF/DataContract we have the KnownTypeAttribute and its constructor accepting a string representing the name of static function to invoke to get a set of Type:s.
[DataContract]
[KnownType("GetTypes")]
public abstract class AbstractContract
{
[DataMember] public int Prop1 { get; set; }
[DataMember] public string Prop2 { get; set; }
static IEnumerable<Type> GetTypes()
{
var list = new List<Type>();
list.Add(typeof(ConcreteContract1));
list.Add(typeof(ConcreteContract2));
return list;
}
}
[DataContract]
public class ConcreteContract1 : AbstractContract
{
[DataMember] public int Prop3 { get; set; }
}
[DataContract]
public class ConcreteContract2 : AbstractContract
{
[DataMember] public bool Prop3 { get; set; }
}
Is this scenario supported?
The scenario with GetTypes() isn't supported, partly due to how to v1 handles the generation/caching -however, in v2 (preview available) this is supoortable:
using System;
using System.Runtime.Serialization;
using ProtoBuf.Meta;
class Program
{
static void Main()
{
var model = TypeModel.Create();
var abst = model.Add(typeof(AbstractContract), true);
// define inheritance here...
abst.AddSubType(10, typeof(ConcreteContract1));
abst.AddSubType(11, typeof(ConcreteContract2));
model.CompileInPlace();
AbstractContract foo = new ConcreteContract1 { Prop1 = 123, Prop2 = "abc", Prop3 = 456 };
AbstractContract bar = (AbstractContract)model.DeepClone(foo);
Console.WriteLine(bar.Prop1);
Console.WriteLine(bar.Prop2);
Console.WriteLine(((ConcreteContract1)bar).Prop3);
}
}
[DataContract]
public abstract class AbstractContract
{
[DataMember(Order=1)]
public int Prop1 { get; set; }
[DataMember(Order=2)]
public string Prop2 { get; set; }
}
[DataContract]
public class ConcreteContract1 : AbstractContract
{
[DataMember(Order=1)]
public int Prop3 { get; set; }
}
[DataContract]
public class ConcreteContract2 : AbstractContract
{
[DataMember(Order=1)]
public bool Prop3 { get; set; }
}
Actually, with this approach you can take away all the attributes if you want (telling it explicitly instead). Note: you should cache and re-use the compiled model as far as possible - it is thread-safe, but generating it each time will be a bit more expensive.

RIA DomainService not generating client code using DataContracts

I'm working on a Silverlight 4.0 application and am using RIA services. I have created a class on the server-side which has DataContract and DataMember attributes applied to it.
A DomainService exposes this class as a query result and as such, generates code for it on the client. But somehow it doesn't generate code for all properties of the class. Primitive properties of type guid, string, int, bool etc are generated just fine, but if I have a property of my own complex type, that property isn't created on the client.
Here's the class in question:
[DataContract]
[KnownType(typeof(SummaryGroup))]
public class SummaryDataSet
{
public SummaryDataSet()
{
}
[KeyAttribute]
[DataMember]
public Guid Guid { get; set; }
[DataMember]
public SummaryGroup SummaryGroup { get; set; }
}
The Guid property is created on the client just fine. The SummaryGroup property isn't created on the client. Here's the code for the SummaryGroup:
[DataContract]
public class SummaryGroup
{
public SummaryGroup()
{
}
[KeyAttribute]
[DataMember]
public Guid Guid { get; set; }
[DataMember]
public string Name { get; set; }
[DataMember]
public int Sequence { get; set; }
}
Both classes are in the same namespace.
Question: why isn't the SummaryGroup property of SummaryDataSet created on the client and what should I do to fix this?
WCF RIA cannot handle complex types, but you could try this:
[DataContract]
[KnownType(typeof(SummaryDataSet))]
public class SummaryDataSet
{
public SummaryDataSet()
{ }
[KeyAttribute]
[DataMember]
public Guid Guid { get; set; }
[DataMember]
[Association("SummarySet_SummaryGrp_FK", "Guid", "Guid")]
public SummaryGroup SummaryGroup { get; set; }
}
This gives RIA the information to connect from the SummaryDataSet to the SummaryGroup.
This assumes that you can request both the SummaryDataSet and SummaryGroup from the serverside service.