wcf newbie question: arrays as properties - c#

I have DataContract class which has property of type List<AnotherObject>. AnotherObject is also marked with DataContract. For some reason this property comes from wcf service as null, althought I fill it at the server. Is that by design?
Here you go. Class definitions:
[DataContract]
public class UserInfo
{
[DataMember]
public decimal UserID
{
get;
protected internal set;
}
[DataMember]
public string UserName
{
get;
protected internal set;
}
[DataMember]
public string Pswd
{
get;
protected internal set;
}
[DataMember]
public List<decimal> RoleID
{
get;
protected internal set;
}
List<UserRole> userRolesTable = new List<UserRole>();
[DataMember]
public List<UserRole> UserRoles
{
get
{
return userRolesTable;
}
protected internal set { }
}
}
[DataContract]
public class UserRole
{
[DataMember]
public decimal ROLEID { get; internal set; }
[DataMember]
public string ROLE_CODE { get; internal set; }
[DataMember]
public string ROLE_DESCRIPTION { get; internal set; }
[DataMember]
public decimal FORMID { get; internal set; }
[DataMember]
public string FORMCODE { get; internal set; }
[DataMember]
public string FORMNAME { get; internal set; }
}
UserRoles property comes as null.

Why are you letting the RoleId property be auto-implemented but not UserRoles? The code as-is won't work because you have an empty setter. You should probably just use an auto-property for it:
[DataMember]
public List<UserRole> UserRoles
{
get; set;
}
Or at least provide a meaningful setter. You setter does nothing, hence the de-serializer can't populate the value.

List<UserRole> userRolesTable = new List<UserRole>();
[DataMember]
public List<UserRole> UserRoles
{
get
{
return userRolesTable;
}
protected internal set { }
}
Your setter is empty. Put some
userRolesTable = value;
Another thing, your DataContract properties should have public setters.

Your Setter on the UserRoles property is set to internal. Because the WCF framework will be setting the property, it gives up assigning the value because it is listed as internal.
http://connect.microsoft.com/data/feedback/details/625985/wcf-client-entities-with-internal-setters-and-internalsvisibletoattribute-on-asmbly-fail
You can do what this link suggests, using the InternalsVisibleToAttribute attribute on that property, but I have never used it.
update
What I am trying to say is that I bet the Serialization works fine, the WCF framework is unable to insert the deserialized value into the host code because based upon the data contract, the internal Setter section of the property is inaccessible. use the InternalVisibleTo attribute to inform the WCF serialization framework access to the setter of the client version of your data contract object.

You need to Implement the setter...
protected internal set { userRolesTable = value; }

Basically, its a serialization problem. I had this problem in my code in the past, but it has been a while, so bear with me.
First, we need to find out if the object relations are null before the WCF call, so put a debug before and after.
If the object is being returned as null before the call, you have a few options:
You can explicitly use .Include("AnotherObject") on your DbContext to get the object. I used this by having my Read method take an array of strings which I used to include all the necessary objects. This is more ideal than automatically taking all objects because during serialization, if you take everything, you could fairly easily end up with your entire database being serialized, which introduces performance and security issues, among other things.
Another option is to use a dynamic proxy by adding the keyword virtual in front of your list. The DataContractSerializer, though, has a problem serializing dynamic proxies, so you will need to implement an attribute that uses the ProxyDataContractResolver instead of DataContractResolver. This attribute needs to be applied on all OperationContracts that can pass a dynamic proxy. This will automatically take ALL object references, which is probably bad coding practice, so I do recommend the above method.
public class ApplyDataContractResolverAttribute : Attribute, IOperationBehavior
{
public ApplyDataContractResolverAttribute() { }
public void AddBindingParameters(OperationDescription description, BindingParameterCollection parameters) { }
public void ApplyClientBehavior(OperationDescription description, System.ServiceModel.Dispatcher.ClientOperation proxy)
{
DataContractSerializerOperationBehavior dataContractSerializerOperationBehavior = description.Behaviors.Find<DataContractSerializerOperationBehavior>();
dataContractSerializerOperationBehavior.DataContractResolver = new ProxyDataContractResolver();
}
public void ApplyDispatchBehavior(OperationDescription description, System.ServiceModel.Dispatcher.DispatchOperation dispatch)
{
DataContractSerializerOperationBehavior dataContractSerializerOperationBehavior = description.Behaviors.Find<DataContractSerializerOperationBehavior>();
dataContractSerializerOperationBehavior.DataContractResolver = new ProxyDataContractResolver();
}
public void Validate(OperationDescription description) { }
}
Edit: Also I think you can have setters in Data Contracts not be public, because I do it and it works fine :). But I would try making your setter public first, then solving the problem, then reverting to a protected setter, just so that you are dealing with as few variables at a time as possible.

Related

Why create public wrappers to private members in a class?

I've always had this question, but I've blindly followed on so far.
This is from a piece of example code:
Why do this:
public class EmployeeInfo
{
int _EmpNo;
public virtual int EmpNo
{
get { return _EmpNo; }
set { _EmpNo = value; }
}
string _EmpName;
public virtual string EmpName
{
get { return _EmpName; }
set { _EmpName = value; }
}
}
when there's nothing additional, such as calculations or validations, being done during getting/setting?
Will this suffice?
public class EmployeeInfo
{
public int EmpNo { get; set; }
public string EmpName { get; set; }
}
Also, why virtual for the public member wrappers?
Why do this?
There's really no reason to since the addition of auto-implemented properties in C# 3.0. It could be legacy code that hasn't been changed, old habits, or keeping consistency with pre-C# 3 code.
Will this suffice?
No - you've converted the virtual properties to non-virtual. So they are not completely equivalent.
The equivalent would be
public class EmployeeInfo
{
public virtual int EmpNo { get; set; }
public virtual string EmpName { get; set; }
}
Also, why virtual for the public member wrappers?
So that a derived class can override the logic for the properties - to add validation, change notification, etc.
When does the shortened form actually have an impact?
When the backing fields are referenced by the internal code of the class (which can be detected at compile-time), or when they're accessed by reflection (which cannot be detected until run-time, or via static code analysis).
An "auto-implemented" property actually gets a backing field created by the compiler, so in that sense they're equivalent if the only place the backing field is referenced is within the property code.
You have two questions. First is changing properties to auto implemented properties, they should be equal, but you removed virtual keyword, that makes them different.
So, what is virtual. That keyword will allow derived classes to override the get/set for the said property.
See: virtual C#
The virtual keyword is used to modify a method, property, indexer, or
event declaration and allow for it to be overridden in a derived
class.
Your class with auto-implemented properties would be equal if you have:
public class EmployeeInfo
{
public virtual int EmpNo { get; set; }
public virtual string EmpName { get; set; }
}
Later you can override a property and leave the other to maintain the parent behaviour, like:
public class ManagerInfo : EmployeeInfo
{
private int _EmpNo;
public override int EmpNo
{
get { return _EmpNo; }
set
{
if (value < 100) throw new Exception("EmpNo for manager must be greater than 100");
_EmpNo = value;
}
}
}
Depends if you want to see the field publicly or not,
if your only going to use the field inside the declaring class then you don't need to wrap it in a property, its only if you need to expose it publicly or down the inheritance tree that you should have the property
public string EmpName { get; set; }
is just a compiler short cut to
private string _EmpName;
public string EmpName {
get{ return _EmpName;}
set(_EmpName = value; }
}
they are functionally identical.
However there are things that the short cut wont let you do, for example you want to raise an event when the property changes.
there there is also your use of Virtual which is an inheritance modifier
Virtual instructs the code that it needs to look DOWN the inheritance tree for a newer implementation.
so in
class A
{
public string Data
{
get{return "A";}
}
public virtual string VData
{
get{return "A";}
}
}
class B:A
{
public new string Data
{
get{return "B";}
}
public override string VData
{
get{return "B";}
}
}
then if you do
A obj = new B();
obj.Data; //return A
obj.VData; //return B
It looks like the code in this form:
$type _$var;
public virtual $type $var
{
get { return _$var; }
set { _$var = value; }
}
Was generated using a tool, template or snippet. As habits hardly ever change and tools, templates and snippets hardly ever get updated, I guess they were created before auto-implemented properties (public $type $var { get; set; }) were introduced to the C# language.
For the code you show, it's perfectly valid to have the equivalent:
public virtual $type $var { get; set; }
As you can override the auto-implemented property and add a backing field, validation and whatever when required.
The expanded form is the traditional way to do it:
public class MyClass
{
int _myInt;
virtual public int MyProperty
{
get
{
return _myInt;
}
set
{
_myInt = value;
}
}
}
However, the shorter form is called "auto properties", introduced in C# 3.0.
public class MyClass
{
virtual public int MyProperty { get; set; }
}
These code blocks are equivalent. This is a good practice for keeping your code concise.
One thing to consider: You aren't able to make the internal variable protected with auto properties, so if you create a derived class and override your property, you'll need to use base.MyProperty to access it, or use the expanded form.

Deserialize object using JSON.NET, but put some properties into a member of the class

I am writing a set of data structures to ingest third-party JSON into (no writing out) using JSON.NET.
I have a case for reading some of the top-level JSON elements into a member object of the object being deserialized into.
My JSON:
{
"Id":1
"Checksum":42
"Name":"adam",
"Hair":true
}
My ideal object structure:
public class EntityHeader
{
int Id { get; set; }
int Checksum { get; set; }
}
public class Entity
{
[HeroicJsonAttribute( "Id", "Checksum" )]
public EntityHeader Header { get; set; }
public string Name { get; set; }
public bool Hair { get; set; }
}
Is there a simple way to achieve this? I will have a number of types which will need this, and I'd hate to have to write a JsonConverter for each.
This question has been asked before, here, but the accepted answer doesn't address the question.
Thanks!
An alternative approach would be to use an EntityHeader field in the Entity class as a backing store for private properties which can be deserialized into:
public class EntityHeader
{
int Id { get; set; }
int Checksum { get; set; }
}
public class Entity
{
private EntityHeader m_Header = new EntityHeader();
public EntityHeader Header { get { return m_Header; } }
[JsonProperty]
private int Id { set { m_Header.Id = value; } }
[JsonProperty]
private int Checksum { set { m_Header.Checksum = value; } }
public string Name { get; set; }
public bool Hair { get; set; }
}
Thus, all the properties in the JSON can be read straight into the Entity object, but consumers of Entity objects have access to a "nicely encapsulated" EntityHeader property.
I haven't tested this, and it may even be kludgey, but it would technically work for me (OP). I am still interested in other answers!
Base on your example you could either; use the adapter pattern:
public class EntityJson
{
int Id { get; set; }
int Checksum { get; set; }
public string Name { get; set; }
public bool Hair { get; set; }
}
// quick/poor example
public class EntityAdapter : IEntity
{
public EntityAdapter(EntityJson model)
{
Header = new Header(); // and populate this objects fields
Name = model.Name; // populate other properties
}
public EntityHeader Header { get; set; }
public string Name { get; set; }
public bool Hair { get; set; }
}
Or abuse the fact that json.net ignores properties not available:
var entity = JsonConvert.Deserialze<Entity>();
var header = JsonConvert.Deserialize<EntityHeader>();
entity.Header = header;
I'm going to go ahead and post this answer which is a little bit too long for a comment, so please take this more as an extended comment than an actual attempt to answer your specific question. And of course, you know your requirements best so this is just my considered opinion :)
With that in mind, my advice is:
Don't do this.
I would instead create a simple DTO class that has a 1-1 relationship to the JSON being received; and I'd put all my validation attributes on the properties of that class.
Once I had deserialised the JSON into this simple DTO, I would then use a mapping layer of some kind (roll your own or use Automapper, etc) to map this DTO into a more meaningful structure such as your Entity class.
My reasoning behind this is because unless your Entity class is itself only a simple DTO (in which case it should be as simple as possible and ideally not be a composite) you are mixing OOP and concerns with data mapping concerns; whilst this in and of itself is not such a bad thing, it only serves to increase the complexity of your code.
Consider for example if your incoming JSON ends up with 30 or 40 properties, and you manage to figure out a way (maybe adapting some of the nice techniques from the other answers) to map it to the Entity class. But what about when something goes wrong - it's going to be much easier to reason about, and therefore debug, a process which you have much more control over; it's also going to be much easier to make special adaptations for odd edge cases where the serialiser behaviour just can't help you out
Granted it's a bit of work to write and maintain these DTOs but not that much - Webtools already does this for you
Reference: At the boundaries, Applications are not Object-Oriented

WCF return Class with object field

I have a Wcf service that works as RestApi
[KnownType(typeof(myClass1))]
[KnownType(typeof(myClass2))]
[KnownType(typeof(myClassAndOther23typesOmmited))]
[DataContract]
public class ApiResult
{
[DataMember]
public bool Success { get; private set; }
[DataMember]
public object Result { get; private set; }
}
Field Result is problematic part, it cannot be serialized as it's an object type. So the question is, how to return proper ApiResult object.
Note
Althought there is KnownTypeAttribute, service throws SerializationException when i try to assign string[] to ApiResult Result field and return to client.
Upd
After trying ApiResult<T>
Service compiled successfully, and intellisense gives this
After few investigations, gathered that those weird type names are made to avoid collisions in service (it's simple hashcode of type which were achieved by GetHash() of literally object),
This is responce to nvoigt solution as couldnt insert image to comment
Why don't you create a generic ApiResult:
[DataContract]
public class ApiResult<T>
{
[DataMember]
public bool Success { get; internal set; }
[DataMember]
public T Result { get; internal set; }
}
That way, your method can actually return a typed value like ApiResult<myClass1> and you don't need any KnownTypes at all.

Custom Attributes and Type Checking

As I havent seen an answer to this question in my Google and site searches I thought I would pose it the great minds on this site.
As C# does not support generic attributes (which does make sense), I was wondering if there is a way to restrict the type of an argument/property to the attribute based on the type it is decorating. Example:
[AttributeUsage(AttributeTargets.Property)]
public class ColumnBindAttribute : Attribute
{
public string ColumnName { get; set; }
public object DefaultValue { get; set; }
}
[ColumnBind(ColumnName = "Category", DefaultValue = "No Category")]
public int CategoryId { get; set; }
Now clearly when I attempt to bind this property to its default value, I will receive a cast error. Curious if there is anyway to enforce the type of DefaultValue to an int or am I limited to a runtime check.
Thanks in advance
As far as I know, there is no way to enforce a type-specific check on a single property of an attribute. However, and let me note that this is not the most elegant solution, you could use polymorphism to your advantage:
[AttributeUsage(AttributeTargets.Property)]
public class ColumnBindAttribute: Attribute
{
public string ColumnName { get; set; }
public object DefaultUntypedValue
{
get;
protected set;
}
}
[AttributeUsage(AttributeTargets.Property)]
public class ColumnBindGenericAttribute<T> : ColumnBindAttribute
{
public T DefaultValue
{
get { return (T)DefaultUntypedValue; }
set { DefaultUntypedValue = value; }
}
}
[AttributeUsage(AttributeTargets.Property)]
public class ColumnBindInt32Attribute: ColumnBindGenericAttribute<int> {}
[ColumnBindInt32(ColumnName = "Category", DefaultValue = 100)]
public int CategoryId { get; set; }
When retrieving an attribute, the search looks for both the specific type, as well as base types, of the attribute actually applied to the member. You could retrieve all of the ColumBindAttributes decorating a member even if they are derived attributes.
EDIT:
Apologies. The code will not compile if any generic type, directly or indirectly, derives from the Attribute type. That makes the ColumnBindGenericAttribute class impossible. I thought I had found a hole in the compiler...turns out its smarter than me. :P

Why does the proxy generated code create a new class when a MessageContract is in my WCF Service?

I have created two WCF Services (Shipping & PDFGenerator). They both, along with my ClientApp, share an assembly named Kyle.Common.Contracts. Within this assembly, I have three classes:
namespace Kyle.Common.Contracts
{
[MessageContract]
public class PDFResponse
{
[MessageHeader]
public string fileName { get; set; }
[MessageBodyMember]
public System.IO.Stream fileStream { get; set; }
}
[MessageContract]
public class PDFRequest
{
[MessageHeader]
public Enums.PDFDocumentNameEnum docType { get; set; }
[MessageHeader]
public int? pk { get; set; }
[MessageHeader]
public string[] emailAddress { get; set; }
[MessageBodyMember]
public Kyle.Common.Contracts.TrackItResult[] trackItResults { get; set; }
}
[DataContract(Name = "TrackResult", Namespace = "http://kyle")]
public class TrackResult
{
[DataMember]
public int SeqNum { get; set; }
[DataMember]
public int ShipmentID { get; set; }
[DataMember]
public string StoreNum { get; set; }
}
}
My PDFGenerator ServiceContract looks like:
namespace Kyle.WCF.PDFDocs
{
[ServiceContract(Namespace="http://kyle")]
public interface IPDFDocsService
{
[OperationContract]
PDFResponse GeneratePDF(PDFRequest request);
[OperationContract]
void GeneratePDFAsync(Kyle.Common.Contracts.Enums.PDFDocumentNameEnum docType, int? pk, string[] emailAddress);
[OperationContract]
Kyle.Common.Contracts.TrackResult[] Test();
}
}
If I comment out the GeneratePDF stub, the proxy generated by VS2010 realizes that Test returns an array of Kyle.Common.Contracts.TrackResult. However, if I leave GeneratePDF there, the proxy refuses to use Kyle.Common.Contracts.TrackResult, and instead creates a new class, ClientApp.PDFDocServices.TrackResult, and uses that as the return type of Test.
Is there a way to force the proxy generator to use Kyle.Common.Contracts.TrackResult whenever I use a MessageContract? Perhaps there's a better method for using a Stream and File Name as return types?
I just don't want to have to create a Copy method to copy from ClientApp.PDFDocServices.TrackResult to Kyle.Common.Contracts.TrackResult, since they should be the exact same class.
After a lot of extra digging, I realize that it was actually the Enum that "broke" it. It has do with the way DataContractSerializer works vs. XmlSerializer. Long story short, the solution was to turn the Enum into a nullable.
[MessageContract]
public class PDFRequest
{
[MessageHeader]
public Enums.PDFDocumentNameEnum? docType { get; set; }
[MessageHeader]
public int? pk { get; set; }
[MessageHeader]
public string[] emailAddress { get; set; }
[MessageBodyMember]
public Kyle.Common.Contracts.TrackItResult[] trackItResults { get; set; }
}
I ran into the same problem (MessageContract+enums) and your post helped me. Indeed if you explicitly set the enum fields to nullable it works. The issue is that when enums are used, WCF uses the XML serializer which cannot tell null from empty string.
There is a detailed explanation of this behaviour here by one of the actual WCF team members.
In the case of document/literal when using bare messages, WCF falls back to XmlSerializer when handling enum types. ... XmlSerializer treats null as missing by default ... we encounter a schema without nillable="true" ... The detection logic for value types currently only handles primitive value types, it does not check for enums.
In other words WCF does not like enums... But hey, it works, you just need to be aware of it!
You can instruct Visual Studio to re-use classes from referenced assemblies. So if your test project has an assembly reference to the Kyle.Common.Contracts assembly, it should re-use those types defined in there rather than adding new client-side proxy classes.
The switch to enable this is on the Advanced page in the Add Service Reference dialog window - it should be on by default:
Make sure that your project
has an assembly reference to the common data contract assembly
that this setting is really ON when you add the service reference

Categories

Resources