Search
Resolved
as By Design Help for as By Design

1
Sign in to vote
0
Sign in to vote
Sign in
to vote
Type: Bug
ID: 497354
Opened: 10/12/2009 8:23:39 AM
Access Restriction: Public
0
Workaround(s)
0
User(s) can reproduce this bug
I am returning a hashtable from a service operation. I have added all the required KnownTypes as shown in the code below. Now when try to generate service proxy using Add as a service reference, the knowntype for the hashtable is not getting generated in the proxy and therefore the issue. If i add the KnowType manually to my proxy as shown below i am able to serialize and deserialize it properly. Probably an issue with add service reference method? My code works perfectly fine if add the service as a library and use channelfactory to create the proxy.
Details (expand)

Product Version

.NET Framework 3.5 SP1
Product Language
English

Operating System
Windows XP
Operating System Language
English

Architecture
x86

Priority
(1=blocking, 2=important, 3=nice to have)
2

Severity
(1=major functionality issue, 2=important functionality issue, 3=nice to have)
2

Steps to Reproduce
Working code when i add the service as a library(as a project reference)

[ServiceContract]
public interface IService1
{

[OperationContract]
[ServiceKnownType(typeof(List<Sales>))]
Hashtable GetFifoByTruck(int pTruckId);
}


[DataContract]
public class Sales
{
[DataMember]
public double totalAmount;
[DataMember]
public string description;
}
[ServiceKnownType("GetAllMyKnownTypes", typeof(KnownTypeContainer))]
public class Service1 : IService1
{
public Hashtable GetFifoByTruck(int pTruckId)
{
Hashtable result = new Hashtable();
result.Add(1, new List<Sales> {
new Sales { totalAmount = 100.00, description = "First sale" },
new Sales { totalAmount = 12345.67, description = "Great sale" },
});
result.Add(2, new List<Sales> {
new Sales { totalAmount = 332.22, description = "Another sale" },
new Sales { totalAmount = 1.33, description = "A small sale" },
});
return result;
}


}
static class KnownTypeContainer
{
public static IEnumerable<Type> GetAllMyKnownTypes(ICustomAttributeProvider p)
{
System.Collections.Generic.List<System.Type> dynamicyTypes =
new System.Collections.Generic.List<System.Type>();
dynamicyTypes.Add(typeof(Sales));
return dynamicyTypes;
}
}
}

Actual Results
When i add the service as a service reference i am unable to deserialize the HashTable because the following is not getting generated in the proxy.

[ServiceKnownType(typeof(System.Collections.Generic.List<Sales>))]

If i generate the client proxy using "Add as service reference" the following proxy is generated but ServiceKnownType is not generated therefore the xml is not getting de serialized.

Please see the cproxy snippet below.

[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(ConfigurationName="ServiceReference1.IService1")]
[ServiceKnownType(typeof(System.Collections.Generic.List<Sales>))] //I added this //manualy. This must be generated automatically and presently it is not getting generated
public interface IService1 {

[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IService1/GetFifoByTruck", ReplyAction="http://tempuri.org/IService1/GetFifoByTruckResponse")]
System.Collections.Hashtable GetFifoByTruck(int pTruckId);
}
Expected Results
I must be able to de serialize the response at the client.
Component Usage
(any information on your scenario that may help in investigating your issue)
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
ServiceHost host = new ServiceHost(typeof(Service1), new Uri(baseAddress));
host.AddServiceEndpoint(typeof(IService1), new BasicHttpBinding(), "");
host.Open();
Console.WriteLine("Host opened");

ChannelFactory<IService1> factory = new ChannelFactory<IService1>(new BasicHttpBinding(), new EndpointAddress(baseAddress));
IService1 proxy = factory.CreateChannel();
Hashtable s = proxy.GetFifoByTruck(1);

((IClientChannel)proxy).Close();
factory.Close();

Console.Write("Press ENTER to close the host");
Console.ReadLine();
host.Close();

}
}
[ServiceContract]
public interface IService1
{

[OperationContract]
[ServiceKnownType(typeof(List<Sales>))]
Hashtable GetFifoByTruck(int pTruckId);
}


[DataContract]
public class Sales
{
[DataMember]
public double totalAmount;
[DataMember]
public string description;
}
[ServiceKnownType("GetAllMyKnownTypes", typeof(KnownTypeContainer))]
public class Service1 : IService1
{
public Hashtable GetFifoByTruck(int pTruckId)
{
Hashtable result = new Hashtable();
result.Add(1, new List<Sales> {
new Sales { totalAmount = 100.00, description = "First sale" },
new Sales { totalAmount = 12345.67, description = "Great sale" },
});
result.Add(2, new List<Sales> {
new Sales { totalAmount = 332.22, description = "Another sale" },
new Sales { totalAmount = 1.33, description = "A small sale" },
});
return result;
}


}
static class KnownTypeContainer
{
public static IEnumerable<Type> GetAllMyKnownTypes(ICustomAttributeProvider p)
{
System.Collections.Generic.List<System.Type> dynamicyTypes =
new System.Collections.Generic.List<System.Type>();
dynamicyTypes.Add(typeof(Sales));
return dynamicyTypes;
}
}
}


How often does this happen?
Always Happens

Have you seen this problem in other versions?
Yes, this happens in all previous versions
File Attachments
0 attachments
Sign in to post a comment.
Posted by Microsoft on 10/13/2009 at 2:51 AM
Thank you for your feedback, We are currently reviewing the issue you have submitted. If this issue is urgent, please contact support directly(http://support.microsoft.com)
Posted by Microsoft on 10/14/2009 at 5:40 PM
Unfortunately, the code you've posted won’t work given the current WCF implementation. We will consider making improvements in this area in future releases that could make this scenario possible. A workaround that would work with add service reference would be making a common dummy type to all possible types that will be in your data. For example:

    [ServiceContract]
    [ServiceKnownType(typeof(Sales))]
    public interface IService1
    {
        [OperationContract]
        Dictionary<int, List<BaseType>> GetFifoByTruck(int pTruckId);
    }

    [DataContract]
    public class BaseType {}

    [DataContract]
    public class Sales : BaseType
    {
        [DataMember]
        public double totalAmount;
        [DataMember]
        public string description;
    }

    public class Service1 : IService1
    {
        public Dictionary<int, List<BaseType>> GetFifoByTruck(int pTruckId)
        {
            Dictionary<int, List<BaseType>> result = new Dictionary<int, List<BaseType>>();
            result.Add(1, new List<BaseType> {
                                new Sales { totalAmount = 100.00, description = "First sale" },
                                new Sales { totalAmount = 12345.67, description = "Great sale" },});
            result.Add(2, new List<BaseType> {
                                new Sales { totalAmount = 332.22, description = "Another sale" },
                                new Sales { totalAmount = 1.33, description = "A small sale" },});
            return result;
        }
    }
Posted by Haripraghash on 10/14/2009 at 9:06 PM
Is this a WCF implementation issue or a ServicecontractGenerator,WsdlImporter and CodeDom issue? Since i am able to get this working if use techniques apart from "Add service reference", i guess this is not a WCF implementation issue.But thanks for taking a look at it.
Posted by Microsoft on 10/15/2009 at 11:03 AM
More specifically, it's a limitation of the service metadata (wsdl+xsd) wcf exposes. There is currently no way to express KnownType relationships between custom types in metadata beyond saying one type extends another type (inheritance). KnownTypes are implied by add service reference/svcutil using this inheritance information. Since in your example there is no common parent (besides object), ASR/svcutil does not know to add the KnownTypes to the proxy based off of the service metadata.