WCF Invalid enum value '1' cannot be deserialized into type - wcf

I have a WCF Service having an Enum:-
[DataContract(Name = "PurchaseType")]
public enum PurchaseType
{
[EnumMember]
Hire Purchase= 0,
[EnumMember]
PCP = 1
}
DataContract as below:-
[DataContract]
public class Purchase
{
[DataMember(Order = 3, IsRequired = true, EmitDefaultValue = false)]
public PurchaseType Type{ get; set; }
}
The enum members have been marked with the "EnumMember" attribute as required - how when I call the method and pass in "1" - I get below error, this should work...
Any pointers appreicated...

You may add the flags to DataContract like this:
[DataContract] [Flags]
You can check out this document for more information.

Related

The DataMember attributes in WCF are not honored when I copy from List to another

When I copy the DataColumns class to the RatesOfPay class, the DataMember attributes in WCF are no longer honored when I use the following code to copy. I want to see results in the order Step8,Step9, Step10 but I get Step10, Step8, Step9 as Order atribute is being ignored and columns are getting sorted alphabetically. . Also the EmitDefaultValue = false attribute is getting ignored and I see steps with null values.
List<DataColumns> source = new List<DataColumns>();
List<RatesOfPay> destination = new List<RatesOfPay>();
destination = source.Select(d => new RatesOfPay
{
step8 = d.column8,
step9= d.column9,
step10 = d.column10
}).ToList();
public class DataColumns
{
[DataMember(Order = 0, Name = "column8", EmitDefaultValue = false)]
public string column8 { get; set; }
[DataMember(Order = 1, Name = "column9", EmitDefaultValue = false)]
public string column9 { get; set; }
[DataMember(Order = 2, Name = "column10", EmitDefaultValue = false)]
public string column10 { get; set; }
}
public class RatesOfPay
{
[DataMember(Order = 0, Name = "Step8", EmitDefaultValue = false)]
public string step8 { get; set; }
[DataMember(Order = 1, Name = "Step9", EmitDefaultValue = false)]
public string step9 { get; set; }
[DataMember(Order = 2, Name = "Step10", EmitDefaultValue = false)]
public string step10 { get; set; }
}
To expand upon my comments, DataMember is used to instruct the DataContractSerializer how to serialize a particular member.
Order tells the DataContractSerializer what order to serialize/deserialize the member in.
EmitDefaultValue tells the DataContractSerialzier whether or not to emit the default values (null for reference types, a given value for value types) when serializing. If it is set to false, null won't be the result - the member will be ommitted. It is true by default.
A couple of examples might help to illustrate this:
First, the class. If you look at the class in the debugger, the properties are going to be listed in ASCII alphabetical order, which means step10 will be listed first. So will column10.
If you look at the serialized XML, you might see something like this:
<column8>abcd</column8>
<column9>defg</column9>
<column10>hijk</column10>
If one of the columns, say column9, was a null string, you'd see this (with EmitDefaultValue set to false) when it was serialized:
<column8>abcd</column8>
<column10>zzzz</column10>
EmitDefaultValue can be a little confusing from a naming perspective. And it has some really fun interactions with IsRequired.

Send a list with appointments through WCF

I would like to send a list of Appointments through WCF. My Interface looks like this:
[ServiceContract]
public interface IServices
{
[OperationContract]
string addAppointments(List<Appointment> appointmentList);
}
If I call my WCF Service I'm always getting the following error:
Type 'Microsoft.Exchange.WebServices.Data.Appointment' cannot be
serialized. Consider marking it with the DataContractAttribute
attribute, and marking all of its members you want serialized with the
DataMemberAttribute attribute. See the Microsoft .NET Framework
documentation for other supported types.
My Service currently looks like this:
class Service : IServices
{
public string addAppointments(List<Appointment> appointmentList)
{
foreach (Appointment app in appointmentList)
{
Console.WriteLine(app.Organizer.Name);
}
return "true";
}
}
It's not your service that's at fault, it's the class your passing, Appointment.
Start by adding [DataContract] to your class. then [DataMember] to each of the properties you'd like to pass.
For example, if you started with:
public class Appointment{
public DateTime Date { get; set; }
public string Name { get; set; }
}
You can make it serializable by WCF's DataContractSerializer by adding those attributes:
[DataContract]
public class Appointment{
[DataMember]
public DateTime Date { get; set; }
[DataMember]
public string Name { get; set; }
}

Solve a circular reference in WCF from my POCOs

I have a couple of classes (for now) and I'm trying to clear up a circular reference between the two since it is killing WCF's serialization.
I am using EF with POCOs in a WCF REST service is that helps. I have simplified my problem down to bare bones for an easy example here:
[ServiceContract]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class Groups
{
[WebGet(UriTemplate = "")]
public Message GetCollection()
{
var message = new Message { Body = "Test message" };
var group = new Group { Title = "Title of group" };
message.Group = group;
group.Messages = new List<Message> { message };
return message;
}
}
public class Message
{
public string Body { get; set; }
public Group Group { get; set; }
}
[DataContract(IsReference = true)]
public class Group
{
public string Title { get; set; }
public ICollection<Message> Messages { get; set; }
}
I have added the [DataContract(IsReference = true)] to the Group class so that the circular reference is cleaned up however my returned results end up like this:
<Message xmlns="http://schemas.datacontract.org/2004/07/LmApi" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Body>Test message</Body>
<Group z:Id="i1" xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/"/>
</Message>
Where are the properties of the Group and how can I get them?
BritishDeveloper,
There are no properties associated with Group. That's why all you see is the ID of 1.
The reason is that as soon as you annotate the Group class with [DataContract(IsReference = true)], you are telling the DataContract serializer that it's no longer a POCO type. It's a DataContract type.
So, to serialize Group with properties, you now need to go ahead and annotate the Title and Message properties with DataMemberAttribute.
An alternative would be use the "preserveObjectReferences", which you can pass as a parameter to DataContractSerializer, DataContractSerializerOperationBehavior, and other classes.
Hope this helps!
I decided to make my own smaller classes that have a constructor that takes an entity and sets all of this lighterweight properties correctly.
Basically it is a very small copy of the class that has just the properties needed in the payload. (Obviously I have excluded the problem navigation properties)
This is similar to Circular References and WCF Here is my answer modified for this case
I had the same problem and resolved it by excluding the navigation property back to the parent from the DataContract
[DataContract]
public partial class Message
{
[DataMember]
public virtual string Body { get; set; }
[DataMember]
public virtual Group Group { get; set; }
}
[DataContract]
public partial class Group
{
[DataMember]
public virtual string Title { get; set; }
public virtual ICollection<Message> Messages {get; set;}
}

Can I prevent a specific datamember from being deserialized?

I have a datacontract like this
[DataContract]
class MyDC
{
[DataMember]
public string DM1;
[DataMember]
public string DM2;
[DataMember]
public string DM3;
}
and sometimes I want to prevent DM2 from being deserialized when being returned from an OperationContract. Something like this:
[OperationContact]
public MyDC GetMyDC()
{
MyDC mdc = new MyDC();
if (condition)
{
// Code to prevent DM2 from being deserialized
}
return mdc;
}
I could always make a new DataContract that has only DM1 and DM3 and generate that from the MyDC instance but I want to see if it is possible to programatically remove DM2. Is it possible? How?
One way to do this is to set the EmitDefaultValue property of the DataMemberAttribute to false:
[DataContract]
class MyDC
{
[DataMember]
public string DM1;
[DataMember(EmitDefaultValue = false)]
public string DM2;
[DataMember]
public string DM3;
}
Then setting this property to null:
[OperationContact]
public MyDC GetMyDC()
{
MyDC mdc = new MyDC();
if (condition)
{
// Code to prevent DM2 from being deserialized
mdc.DM2 = null;
}
return mdc;
}
This way, that property doesn't get written to the output stream on serialization.
http://msdn.microsoft.com/en-us/library/aa347792.aspx
What you mean is serialization and not deserialization.
If you prepare a class for serialization applying the [DataContract] attribute to the class, only the members of the class that has [DataMember] attribute will be serialized:
[DataContract]
class MyDC
{
[DataMember]
public string DM1;
public string DM2;
[DataMember]
public string DM3;
}
In some more complex cases the usage of [IgnoreDataMember] can solve your problem. (See http://msdn.microsoft.com/en-us/library/ms733127.aspx)
By the way, you can serialize fields and properties, regardless of accessibility: private, protected, internal, protected internal, or public. You can serialize any read/write properties and not only fields. About serialization of collection types see http://msdn.microsoft.com/en-us/library/aa347850.aspx.
[DataContract]
class MyDC
{
[DataMember]
public string DM1;
public string DM2;
public bool IsDM2Serializable;
[DataMember(Name="DM2", EmitDefaultValue = false)]
public string DM2SerializedConditionally
{
get
{
if(IsDM2Serializable)
return null;
return DM2;
}
set { DM2=value; }
}
[DataMember]
public string DM3;
}
Then set IsDM2Serializable to false when you need to hide it:
[OperationContact]
public MyDC GetMyDC()
{
MyDC mdc = new MyDC();
if (condition)
{
// Code to prevent DM2 from being serialized
mdc.IsDM2Serializable = false;
}
return mdc;
}
Yes, we can prevent an attribute from serialization.
Put [DataContract] Annotation on class and [DataMember] for only serialized attribute. if you want to skip attribute when that attribute value is null then put [DataMember(EmitDefaultValue = false)] on that attribute.
Example:
[DataContract]
public class MyClass
{
[DataMember]
public int Id{ get; set; }
[DataMember]
public string Title { get; set; }
[DataMember]
public string MessageBody { get; set; }
[DataMember(EmitDefaultValue = false)]
public DateTime SentOn { get; set; }
}
Note: SentOn will be serialized when it is not null and others will be serialized in every condition.

WCF Rest client and Transfer Encoding Chunked: Is it supported?

I have a datacontract as defined below:
[DataContract(Namespace="",Name="community")]
public class Community {
[DataMember(Name="id")]
public int Id{get; set;}
[DataMember(Name="name")]
public string Name { get; set; }
[DataMember(Name="description")]
public string Description { get; set; }
}
and the service contract goes like this:
[OperationContract]
[WebGet(
BodyStyle = WebMessageBodyStyle.Bare,
ResponseFormat = WebMessageFormat.Xml,
UriTemplate = "{id}"
)]
Community GetCommunity(string id);
When I make a rest call to the host, I get data but only Id and Name properties are populated. The Description property is null! I am creating the channel by inheriting from ClientBase.
Does anybody know why WCF serializes Id and Name but not Description? The Transfer Encoding is set to 'Chunked' on the response from the host and I would like to know if that has anything to do with it ?
I found out that some of the properties were not getting serialized because the response xml had the elements in a different order. The solution was to explicitly set serialization order on the datacontract. Here is the datacontract after I added order attribute:
[DataContract(Namespace="",Name="community")]
public class Community
{
[DataMember(Name = "name",Order=2)]
public string Name { get; set; }
[DataMember(Name="id",Order = 1)]
public int Id{get; set;}
[DataMember(Name="description",Order=3)]
public string Description { get; set; }
}