Enumerations don''t work correctly with svcutil or .svc generated schemas

There is a bug when the svc file automatically creates schemas where enumerated values are included in the method parameter list. I included an enum with no data contract, which is supposed to work fine as the enum is automatically serializeable. When I viewed the schema that was automatically created from the .svc file, the EnumerationValue element was missing for one of the enum values.

Also, with the enum values as method parameters, there are errors generated from svcutil (to C#) when creating the code for the class. I get errors that DataContractAttribute and EnumMemberAttribute do not exist in System.Runtime.Serialization. When I removed these attributes from the .cs file, my client code ran fine, but am I going to have to call all of my clients and tell them to remove these attributes so their code works?

Also, when is SvcUtil going to work for code written in C++/CLI? When I run code from C++/CLI that uses a web reference (which I have heard uses svcutil in the background), I get an unhandled exception because a SOAP header Action was not understood.

[1098 byte] By [jvshore] at [2008-1-8]
# 1
could you post a code snippet that will repro the problem?
James.Zhang-MSFT at 2007-10-2 > top of Msdn Tech,Visual Studio Orcas,Windows Communication Foundation (Indigo)...
# 2

This is the C++/CLI code (implementation file excluded):

INTERFACE FILE:

// CallRouting.h

#pragma once

using namespace System;
using namespace System::Xml;
using namespace System:Tongue TiederviceModel;
using namespace System:Tongue TiederviceModel::Channels;
using namespace System::Runtime:Tongue Tiederialization;
using namespace VPBXEnums;

#include <msclr\com\ptr.h>

namespace VPBXCallRouting {
[ServiceContract(Namespace="http://virtualpbx.com/webservices/2007/08/08")]
public interface class ICallRouting
{
[OperationContract]
String^ Login(String^ dnis, long extensionID, String^ password);

[OperationContract]
String^ getInfo(String^ sessionID);

[OperationContract]
void setScreening(String^ sessionID, bool toScreen);

[OperationContract]
void setFollowMe(String^ sessionID, bool toFollow);

[OperationContract]
void setAvailability(String^ sessionID, bool avail);

[OperationContract]
void setDefaultContactByID(String^ sessionID, VConsoleEnums::ContactID contactID);

[OperationContract]
void setDefaultContactByANI(String^ sessionID, String^ phoneNumber);

[OperationContract]
void setFollowMeContactByID(String^ sessionID, VConsoleEnums::ContactID contactID, bool toFollow);

[OperationContract]
void setFollowMeContactByANI(String^ sessionID, String^ phoneNumber, bool toFollow);

[OperationContract]
void setContactNumberInfo(String^ sessionID, VConsoleEnums::ContactID contactID, String^ ANI, bool isDefault, bool isDirectConnect,
bool isPasswordEnabled, bool followMeExclude, VConsoleEnums::RingNoAnswerTO ringNoAnswerTO, bool ringNoAnswerOverride);
};

[ServiceBehavior(Namespace="http://virtualpbx.com/webservices/2007/08/08")]
public ref class CallRouting : ICallRouting
{
public:
CallRouting() { m_cookiePtr.CreateInstance("VPBXCookieManager.CookieManager"); }

virtual String^ Login(String^ dnis, long extensionID, String^ password);
virtual String^ getInfo(String^ sessionID);
virtual void setScreening(String^ sessionID, bool toScreen);
virtual void setFollowMe(String^ sessionID, bool toFollow);
virtual void setAvailability(String^ sessionID, bool avail);
virtual void setDefaultContactByID(String^ sessionID, VConsoleEnums::ContactID contactID);
virtual void setDefaultContactByANI(String^ sessionID, String^ phoneNumber);
virtual void setFollowMeContactByID(String^ sessionID, VConsoleEnums::ContactID contactID, bool toFollow);
virtual void setFollowMeContactByANI(String^ sessionID, String^ phoneNumber, bool toFollow);
virtual void setContactNumberInfo(String^ sessionID, VConsoleEnums::ContactID contactID, String^ ANI, bool isDefault, bool isDirectConnect,
bool isPasswordEnabled, bool followMeExclude, VConsoleEnums::RingNoAnswerTO ringNoAnswerTO, bool ringNoAnswerOverride);

private:
msclr::com:Stick out tonguetr<ICookiePersist> m_cookiePtr;

String^ CreateSession(String^ contents);
String^ ReadSessionInfo(String^ sessionID);
String^ MakeGatewayCall(String^ resource, String^ params);
};
}

INCLUDED ENUM FILE, DEFINING ContactID and RingNoAnswerTO enumerations:

// VPBXEnums.h

#pragma once

using namespace System;

namespace VPBXEnums {
public ref class VConsoleEnums abstract sealed
{
public:
static enum struct ContactID
{
Contact1 = 1,
Contact2 = 2,
Contact3 = 3,
Contact4 = 4
};

static enum struct RingNoAnswerTO
{
RnaTO10 = 10,
RnaTO20 = 20,
RnaTO30 = 30,
RnaTO45 = 45,
RnaTO60 = 60,
RnaTO120 = 120
};
};
}

OUTPUT SCHEMA:

<?xml version="1.0" encoding="utf-8"?>
<xsTongue Tiedchema xmlns:tns="http://schemas.datacontract.org/2004/07/VPBXEnums" elementFormDefault="qualified" targetNamespace="http://schemas.datacontract.org/2004/07/VPBXEnums" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:import schemaLocation="https://vconsole.virtualpbx.com/CallRouting/CallRouting_1.xsd" namespace="http://schemas.microsoft.com/2003/10/Serialization/" />
<xsTongue TiedimpleType name="VConsoleEnums.ContactID">
<xs:restriction base="xsTongue Tiedtring">
<xs:enumeration value="Contact4">
<xs:annotation>
<xs:appinfo>
<EnumerationValue xmlns="http://schemas.microsoft.com/2003/10/Serialization/">4</EnumerationValue>
</xs:appinfo>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="Contact3">
<xs:annotation>
<xs:appinfo>
<EnumerationValue xmlns="http://schemas.microsoft.com/2003/10/Serialization/">3</EnumerationValue>
</xs:appinfo>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="Contact2">
<xs:enumeration value="Contact1">
<xs:annotation>
<xs:appinfo>
<EnumerationValue xmlns="http://schemas.microsoft.com/2003/10/Serialization/">1</EnumerationValue>
</xs:appinfo>
</xs:annotation>
</xs:enumeration>
</xs:restriction>
</xsTongue TiedimpleType>
<xs:element name="VConsoleEnums.ContactID" nillable="true" type="tns:VConsoleEnums.ContactID" />
<xsTongue TiedimpleType name="VConsoleEnums.RingNoAnswerTO">
<xs:restriction base="xsTongue Tiedtring">
<xs:enumeration value="RnaTO120">
<xs:annotation>
<xs:appinfo>
<EnumerationValue xmlns="http://schemas.microsoft.com/2003/10/Serialization/">120</EnumerationValue>
</xs:appinfo>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="RnaTO60">
<xs:annotation>
<xs:appinfo>
<EnumerationValue xmlns="http://schemas.microsoft.com/2003/10/Serialization/">60</EnumerationValue>
</xs:appinfo>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="RnaTO45">
<xs:annotation>
<xs:appinfo>
<EnumerationValue xmlns="http://schemas.microsoft.com/2003/10/Serialization/">45</EnumerationValue>
</xs:appinfo>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="RnaTO30">
<xs:annotation>
<xs:appinfo>
<EnumerationValue xmlns="http://schemas.microsoft.com/2003/10/Serialization/">30</EnumerationValue>
</xs:appinfo>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="RnaTO20">
<xs:annotation>
<xs:appinfo>
<EnumerationValue xmlns="http://schemas.microsoft.com/2003/10/Serialization/">20</EnumerationValue>
</xs:appinfo>
</xs:annotation>
</xs:enumeration>
<xs:enumeration value="RnaTO10">
<xs:annotation>
<xs:appinfo>
<EnumerationValue xmlns="http://schemas.microsoft.com/2003/10/Serialization/">10</EnumerationValue>
</xs:appinfo>
</xs:annotation>
</xs:enumeration>
</xs:restriction>
</xsTongue TiedimpleType>
<xs:element name="VConsoleEnums.RingNoAnswerTO" nillable="true" type="tns:VConsoleEnums.RingNoAnswerTO" />
</xsTongue Tiedchema>

PORTION OF GENERATED .cs from svcutil:

namespace VPBXEnums
{
using System.Runtime.Serialization;

[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "3.0.0.0")]
[System.Runtime.Serialization.DataContractAttribute(Name="VConsoleEnums.ContactID")]
public enum VConsoleEnumsContactID : int
{

[System.Runtime.Serialization.EnumMemberAttribute()]
Contact4 = 4,

[System.Runtime.Serialization.EnumMemberAttribute()]
Contact3 = 3,

[System.Runtime.Serialization.EnumMemberAttribute()]
Contact2 = 2,

[System.Runtime.Serialization.EnumMemberAttribute()]
Contact1 = 1,
}

[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "3.0.0.0")]
[System.Runtime.Serialization.DataContractAttribute(Name="VConsoleEnums.RingNoAnswerTO")]
public enum VConsoleEnumsRingNoAnswerTO : int
{

[System.Runtime.Serialization.EnumMemberAttribute()]
RnaTO120 = 120,

[System.Runtime.Serialization.EnumMemberAttribute()]
RnaTO60 = 60,

[System.Runtime.Serialization.EnumMemberAttribute()]
RnaTO45 = 45,

[System.Runtime.Serialization.EnumMemberAttribute()]
RnaTO30 = 30,

[System.Runtime.Serialization.EnumMemberAttribute()]
RnaTO20 = 20,

[System.Runtime.Serialization.EnumMemberAttribute()]
RnaTO10 = 10,
}
}

As you can see, the enumeration for contactid is incorrect, as contact2 does not have own enumerated section. Also, as you can see from the .cs sample, an error is produced at compile time because DataContractAttribute and EnumMemberAttribute are not part of System.Runtime.Serialization. If you take out these attributes, you can recompile fine.

Another really important thing: The .svc file used for the web service does not work in a load balanced environment, since it hard codes the schema paths with the machine name. There should be an additional query parameter to the svc file where you can submit the domain name, so it will override the machine name. As it stands now, if I want the .svc file to be used to produce the wsdl and schema for me, I have to set the external reference to a wsdl file I created and create the xsds files, putting the wsdl and xsd files in the virtual directory.

Thanks,

John Shore

jvshore at 2007-10-2 > top of Msdn Tech,Visual Studio Orcas,Windows Communication Foundation (Indigo)...
# 3

From MSDN:

http://msdn2.microsoft.com/en-us/library/system.runtime.serialization.datacontractattribute.aspx

DataContractAttribute and EnumMemberAttribute are part of the System.RuntimeSerialization namespace.

James.Zhang-MSFT at 2007-10-2 > top of Msdn Tech,Visual Studio Orcas,Windows Communication Foundation (Indigo)...
# 4

Of course they are, that is why I am baffled by the compile error raised when attempting to compile the .cs class that was produced by svcutil.

jvshore at 2007-10-2 > top of Msdn Tech,Visual Studio Orcas,Windows Communication Foundation (Indigo)...
# 5

I have posted 3 issues that I feel that need to be addressed by the WCF team at Microsoft, considering all 3 issues would prohibit people from using the WCF framework for web services. The biggest issue is that the wsdl and xsd files are created with the machine name hardcoded, when this will prohibit anyone from using WCF in a load balanced environment. The second biggest issue is that when using enumerated values in a contract hosted in WCF, svcutil produces a .cs file that gives compile errors indicating DataContractAttribute and EnumMemberAttribute are not part of the System.RuntimeSerialization namespace, which is false. The third issue is that the xsd that is produced from the contract with a enumerated parameter is incorrect, as it missed one of the enumerated values (like I posted in my code). I posted my code, as requested. If you need me to email the actual files for testing, that would also be no problem. I would greatly appreciate it if these issues could be quickly addressed considering my company has spent time and money developing their web service solution with WCF as the framework.

John Shore

jvshore at 2007-10-2 > top of Msdn Tech,Visual Studio Orcas,Windows Communication Foundation (Indigo)...
# 6
John, send over the stuff to me (christian.weyer __AT__ thinktecture.com) - I will take care of talking to the WCF team about this.
ChristianWeyer at 2007-10-2 > top of Msdn Tech,Visual Studio Orcas,Windows Communication Foundation (Indigo)...

Visual Studio Orcas

Site Classified