Using Enum in return types with DataContract
-
Thursday, July 30, 2009 2:29 AM
I am trying to return an Enum type within a class.
This is the interface that is shared to the client....
using System;
When i call GetNextActionReport() the method itself on the service will return the correct object values. But the client will receive the error:
using System.ServiceModel;
using PcSanity.Classes;
namespace PcSanity.Interfaces
{
[ServiceContract(
ConfigurationName = "PSVP",
Name = "PSVP",
Namespace = "PcSanity.Interfaces.ISharedService",
ProtectionLevel = System.Net.Security.ProtectionLevel.EncryptAndSign)]
public interface ISharedService
{
string Version
{
[OperationContract]
get;
}
[OperationContract]
string GetCurrentLog();
[OperationContract]
string GetEntireLog();
[OperationContract]
int GetActionReportListLength();
[OperationContract]
ActionReport GetNextActionReport();
[OperationContract]
void ActionReportReturn(ActionReport Report);
}
}
'comminucationexecption occured' :: 'There was an error reading from the pipe: The pipe has been ended. (109, 0x6d).'
I have traced the error to the enum types in this class which is the ActionReport.
using System;
And here is the code that makes the exception.
using PcSanity.Classes;
using System.Runtime.Serialization;
namespace PcSanity.Classes
{
[DataContract]
public class ActionReport
{
[DataMember]
protected ActionReportType pType;
[DataMember(IsRequired = false)]
protected ActionReportResponse pResponse;
[DataMember(IsRequired = false)]
protected string pNewRunItemName;
[DataMember(IsRequired=false)]
protected string pOldRunItemName;
public ActionReport(ActionReportType Type, string NewRunItemName)
{
pType = Type;
pNewRunItemName = NewRunItemName;
}
public ActionReport(ActionReportType Type, string NewRunItemName, string OldRunItemName)
{
pType = Type;
pNewRunItemName = NewRunItemName;
pOldRunItemName = OldRunItemName;
}
public ActionReportType Type
{
get
{
return pType;
}
}
public string NewRunItem
{
get
{
return pNewRunItemName;
}
}
public string OldRunItem
{
get
{
return pOldRunItemName;
}
}
public ActionReportResponse Response
{
get
{
return pResponse;
}
}
}
[DataContract(Name="ActionReportType")]
public enum ActionReportType
{
[EnumMember]
IsNull=666,
[EnumMember]
RunItem_New=101,
[EnumMember]
RunItem_CommandUpdated=102,
[EnumMember]
RunItem_UsernameUpdated = 102,
[EnumMember]
RunItem_FileHashChanged=103,
[EnumMember]
RunItem_RegistryLocationUpdated=104,
}
[DataContract(Name="ActionReportResponse")]
public enum ActionReportResponse
{
[EnumMember]
RunItem_AllowNew=1011,
[EnumMember]
RunItem_DenyNew=1010,
[EnumMember]
RunItem_AllowUpdate=1021,
[EnumMember]
RunItem_DenyUpdate=1020,
[EnumMember]
RunItem_AllowFileChanged=1031,
[EnumMember]
RunItem_DenyFileChanged=1030
}
}
// Create channel to service
VirusProtectionChannel = new ChannelFactory<ISharedService>
(new NetNamedPipeBinding(NetNamedPipeSecurityMode.Transport), new EndpointAddress("net.pipe://localhost/PSVP"));
VirusProtectionService = VirusProtectionChannel.CreateChannel();
// Set dialog text
Text = "Virus Protection Tray v" + VirusProtectionService.Version;
int iActionReportCount = VirusProtectionService.GetActionReportListLength();
if (iActionReportCount > 0)
{
ActionReport aReport = VirusProtectionService.GetNextActionReport();
}
All Replies
-
Thursday, July 30, 2009 2:48 AMHi,
Sorry, could you explain what did you mean with this: "I have traced the error to the enum types in this class which is the ActionReport".
Did you enable WCF tracing to get more info on the error?.
Regards,
Rodrigo. -
Thursday, July 30, 2009 2:54 AMIf i remove the enum properties from the ActionReport class, it will return to the client proxy without the error.
-
Thursday, July 30, 2009 2:57 AMCould you please enable tracing (http://msdn.microsoft.com/en-us/library/ms733025.aspx) to find more info on the issue?.
Regards,
Rodrigo. -
Thursday, July 30, 2009 3:18 AMi have enabled tracing now. Not giving me more information though.
I added:
[DataContract]
public enum RunType
{
[EnumMember]
Debug=1,
[EnumMember]
Release=0,
}
and updated:
[ServiceContract]
public interface ISharedService
{
string Version
{
[OperationContract]
get;
}
RunType GetRunMode
{
[OperationContract]
get;
}
[OperationContract]
string GetCurrentLog();
[OperationContract]
string GetEntireLog();
[OperationContract]
int GetActionReportListLength();
[OperationContract]
ActionReport GetNextActionReport();
[OperationContract]
void ActionReportReturn(ActionReport Report);
}
if the service returns GetRunMode as debug, my client gets it fine with this code above.
BUT with ActionReport GetNextActionReport();
I want it to return this class.
using System;
using PcSanity.Classes;
using System.Runtime.Serialization;
namespace PcSanity.Classes
{
[DataContract]
public class ActionReport
{
[DataMember]
protected ActionReportType pType;
[DataMember]
protected ActionReportResponse pResponse;
[DataMember]
protected string pNewRunItemName;
[DataMember]
protected string pOldRunItemName;
public ActionReport(ActionReportType Type, string NewRunItemName)
{
pType = Type;
pNewRunItemName = NewRunItemName;
}
public ActionReport(ActionReportType Type, string NewRunItemName, string OldRunItemName)
{
pType = Type;
pNewRunItemName = NewRunItemName;
pOldRunItemName = OldRunItemName;
}
public ActionReportType Type
{
get
{
return pType;
}
}
public string NewRunItem
{
get
{
return pNewRunItemName;
}
}
public string OldRunItem
{
get
{
return pOldRunItemName;
}
}
public ActionReportResponse Response
{
get
{
return pResponse;
}
}
}
[DataContract]
public enum ActionReportType
{
[EnumMember]
IsNull=666,
[EnumMember]
RunItem_New=101,
[EnumMember]
RunItem_CommandUpdated=102,
[EnumMember]
RunItem_UsernameUpdated = 102,
[EnumMember]
RunItem_FileHashChanged=103,
[EnumMember]
RunItem_RegistryLocationUpdated=104,
}
[DataContract]
public enum ActionReportResponse
{
[EnumMember]
RunItem_AllowNew=1011,
[EnumMember]
RunItem_DenyNew=1010,
[EnumMember]
RunItem_AllowUpdate=1021,
[EnumMember]
RunItem_DenyUpdate=1020,
[EnumMember]
RunItem_AllowFileChanged=1031,
[EnumMember]
RunItem_DenyFileChanged=1030
}
}
I am stumped, and would prefer to return the above class -
Thursday, July 30, 2009 3:38 AM
Hi,
I've tried your code, I've enabled tracing and this is what I get:
There was an error while trying to serialize parameter http://tempuri.org/:DoWorkResult. The InnerException message was 'Enum value '0' is invalid for type 'ActionReportResponse' and cannot be serialized. Ensure that the necessary enum values are present and are marked with EnumMemberAttribute attribute if the type has DataContractAttribute attribute.'. Please see InnerException for more details.
The problem here is that you're not initializing the ActionReportResponse and it is taking the default (and invalid) value of '0'... so it cannot be serialized.
Add some valid default value for this member in your constructor or define some Default enum member with value '0' and it will work ok.
Regards,
Rodrigo.- Marked As Answer by Spiral Galaxy Thursday, July 30, 2009 3:52 AM
-
Thursday, July 30, 2009 3:53 AMAwsome,
Thanks rfreire.
Ps. I had to restart my machine before the tracing would word, doh.
All resolved. -
Monday, June 07, 2010 6:56 PMAs a late follow up, the answer on this post was indeed helpful, but I found that adding a '0' value to the Enum was the only working solution. Adding a statement to the constructor of the class setting a default value didn't even get processed by the proxy on the client, and the exception was still thrown. Only when a value of '0' was added to the enum did the problem get solved. Of course this is only an issue if the client has chosen not to populate the enum property and leave it as its default value.
-
Wednesday, December 15, 2010 9:17 PM
Just want to record my findings in case it'll help someone. What people have suggested include
1) add value 0 into your enum
2) set the enum value in consturctor of containining type
And what I found working is to mark IsRequired to true on the enum member of your data contract
DataMember(IsRequired=true)] -
Wednesday, May 15, 2013 4:30 AMthanks for the answer @rfreire
,, I tried to set a 0 value for one of the enum values , and adding the MemberShip attribute this did not solve the issue , i worked around it by setting a default value in object constructor ,,,
hope this may help another one ,,Thanks Mohd Al-Bakri

