brucezhang80 / protobuf-net

Automatically exported from code.google.com/p/protobuf-net
Other
0 stars 0 forks source link

Error with WCF-Service enum parameter passing (deserialization) #382

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
What steps will reproduce the problem?

1. Create a enum (with or without the ProtoEnum attributes)

[Serializable]
[DataContract]
[ProtoContract(Name = "DashboardType")]
[Flags]
public enum DashboardType
{
    [EnumMember(Value = "Error")]
    [ProtoEnum(Name = "Error", Value = 0)]
    ERROR,
    [EnumMember(Value = "DRILLDOWNNCHART")]
    [ProtoEnum(Name = "DRILLDOWNNCHART", Value = 1)]
    DRILLDOWNNCHART
}

2. Create a service interface with the enum parameter

[OperationContract]
OperatingNumberData GetOperatingNumber(String operatingNumberName, 
DashboardType dt, DateTime start, DateTime end);

3. Now call the service method from the silverlight client with this call

ac.GetOperatingNumberAsync(Name, DashboardType.DRILLDOWNCHART, DateStart, 
DateEnd);

What is the expected output? What do you see instead?
The expected output in the ApplicationService is the 
DashboardType.DRILLDOWNCHART, but it will deserialize always the first/default 
enum type (DashboardType.ERROR)

public OperatingNumberData GetOperatingNumber(String operatingNumberName, 
DashboardType dt, DateTime start, DateTime end)
{
    switch (operatingNumberName)
    {
        case "Auftragsbestätigungen":
            return new OperatingNumberData()
            {
                Name = operatingNumberName,
                DashboardType = dt,
                DateStart = start,
                DateEnd = end,
                GridData = GetTableByQuery("SELECT * FROM Table WHERE Datum BETWEEN @start AND @end", start, end)
            };
        default:
            return new OperatingNumberData()
            {
                Name = operatingNumberName,
                DashboardType = dt,
                DateStart = start,
                DateEnd = end,
                GridData = new List<Dictionary<String, Object>>()
            };
    }
}

The request body is this:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<GetOperatingNumber xmlns="http://tempuri.org/">
  <operatingNumberName>Auftragsbestätigungen</operatingNumberName>
  <dt>DRILLDOWNNCHART</dt>
  <start>2011-01-01T00:00:00</start>
  <end>2013-12-31T00:00:00</end>
</GetOperatingNumber>
</s:Body>
</s:Envelope>

The app.xaml is configured this way:

<endpoint address="http://localhost:11111/ApplicationService" 
binding="basicHttpBinding" bindingConfiguration="basicHttp" 
behaviorConfiguration="protoEndpointBehavior" name="CockpitEP" 
bindingName="basicHttp" 
contract="SSG.KPIMonitor.DataService.IApplicationService" />

<behavior name="protoEndpointBehavior">
  <protobuf />
</behavior>

<add name="protobuf" type="ProtoBuf.ServiceModel.ProtoBehaviorExtension, 
protobuf-net, Version=2.0.0.622, &#xD;&#xA;          Culture=neutral, 
PublicKeyToken=257b51d87d2e4d67" />

If i remove the "behaviorConfiguration" it will work as expected over the 
DataContractSerializer with the same source.

What version of the product are you using? On what operating system?

Protobuf: 2.0.0.622
OS: Microsoft Windows [Version 6.1.7601]
Silverlight: 5
.Net Framework: 4.5

Original issue reported on code.google.com by richard....@gmail.com on 24 May 2013 at 11:07

GoogleCodeExporter commented 9 years ago
As an example:

public OperatingNumberData GetOperatingNumber(String operatingNumberName, 
DashboardType dt, DateTime start, DateTime end)
{
    var x = new OperatingNumberData()
    {
        Name = operatingNumberName,
        DashboardType = dt,
        DateStart = start,
        DateEnd = end,
        GridData = new List<Dictionary<String, Object>>()
    };
    return x;
}

Will return:
{SSG.KPIMonitor.DataService.Data.DTO.OperatingNumberData}
    DashboardType: ERROR
    DateEnd: {31.12.2013 00:00:00}
    DateStart: {01.01.2011 00:00:00}
    GridData: Count = 0
    Name: "Reklamationsquote"

Instead of:
{SSG.KPIMonitor.DataService.Data.DTO.OperatingNumberData}
    DashboardType: DRILLDOWNNCHART
    DateEnd: {31.12.2013 00:00:00}
    DateStart: {01.01.2011 00:00:00}
    GridData: Count = 0
    Name: "Reklamationsquote"

The ServiceReference will serialize the enumeration this way:
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", 
"4.0.0.0")]
[System.FlagsAttribute()]
[System.Runtime.Serialization.DataContractAttribute(Name="DashboardType", 
Namespace="http://schemas.datacontract.org/2004/07/SSG.KPIMonitor.DataService.Da
ta.DTO")]
public enum DashboardType : int {
    [System.Runtime.Serialization.EnumMemberAttribute()]
    Error = 0,
    [System.Runtime.Serialization.EnumMemberAttribute()]
    DRILLDOWNNCHART = 1,
}

So the type should be an integer, but if i look at the request header, it seems 
to be a string, else there would be a "1" instead of "DRILLDOWNCHART"
<dt>DRILLDOWNNCHART</dt>
<dt>1</dt>

Is that the possible source of this error? because it can't deserialize the 
string to  the enumeration, because it requests an integer?

Original comment by richard....@gmail.com on 24 May 2013 at 11:17