Poser une questionPoser une question
 

TraitéeWCF & KnownType : Weird Behaviour

  • jeudi 2 juillet 2009 04:32ArefK Médailles de l'utilisateurMédailles de l'utilisateurMédailles de l'utilisateurMédailles de l'utilisateurMédailles de l'utilisateur
     
    Dear All,
    I am new to WCF and I checked out the forum to find a solution but found nothing.
    BTW, I have a base class called BaseData which is defined as bellow:

        [DataContract(Namespace = "http://localhost/KnownType")]
        [KnownType(typeof(SubData))]
        public class BaseData
        {
            [DataMember]
            public virtual int ID
            {
                get;
                set;
            }
        }

    There is also a derived class called SubData:

        [DataContract(Namespace = "http://localhost/KnownType")]
        public class SubData :BaseData
        {
            [DataMember]
            public override int ID {get;set;}
        }

    As you see SubData overrides ID property. Therefore, at client side, an instance of either BaseData or SubData must have a ID property. Bur surprisingly when I create a proxy using Visual Studio, I see that an instance of BaseData has an ID , but an instance of SubData doesn't. Why it is like that??
    For your info I will bring the definition of the ServiceContract here:

    [ServiceContract]
        public interface IKnownType
        {
            [OperationContract]
            SubData GetData();
        }

        [ServiceBehavior(Namespace = "http://localhost/KnownType")]
        public class KnownType : IKnownType
        {
            public SubData GetData()
            {
                return new SubData() { ID = 10 };
            }
        }

Réponses

  • jeudi 2 juillet 2009 14:18Dhananjay25 Médailles de l'utilisateurMédailles de l'utilisateurMédailles de l'utilisateurMédailles de l'utilisateurMédailles de l'utilisateur
     TraitéeA du code
    Hi AreFk, 

    See  There is no probelm in your code. It is working fine for me .  You just remove your service refernece and add it again at client.  For your better undersatding , I have pasted 4 different combinations for  your code and 3rd and 4th combination is working fine. 

    So , there is no probelem in your code 

    1. Just rebuild the service 
    2. Host it again 
    3. update serveice reference at cleint and you are done my dear friend 

    I tried out three combinations to answer you . 
    First is  I replaced [DataContract]  of base class with Serilizable attribute. And I left service implentation as same of your implentation . 

        [Serializable]
        public class BaseData
        {
            [DataMember]
            public int ID { get; set; }
        }
        [DataContract]
        public class SubData:BaseData 
        {
            [DataMember]
    
            public int ID { get; set; }
        }
    }
    
    
     Surprisngly at the client side ,  I  am getting two ID , ID1 ( I know , why I am getting two ID because , I am not overriding the ID field). But I am getting ID property exposed for the subclass .

                Service1Client proxy = new Service1Client();
                SubData obj = new SubData();
                obj.ID = 9;
                obj.ID1 = 10; 
                Console.WriteLine(obj.ID);
                Console.WriteLine(obj.ID1);
                Console.ReadKey(true);
    
    Second , when I changed the class like below 
    [Serializable]
        public class BaseData
        {
            [DataMember]
            public  virtual int ID { get; set; }
        }
        [DataContract]
        public class SubData:BaseData 
        {
            [DataMember]
    
            public  override  int ID { get; set; }
        }
    


    I am not getting ID for either of the class.  where aas I am getting Idk_backingField. I am not sure whether, it is substitution of ID property  ?

                Service1Client proxy = new Service1Client();
                SubData obj = new SubData();
                BaseData baseobj = new BaseData();
                baseobj.IDk__BackingField = 10;
                obj.IDk__BackingField = 10;
                Console.WriteLine(obj.IDk__BackingField);
               Console.WriteLine(baseobj.IDk__BackingField);
                Console.ReadKey(true);
                         
    
    3rd try which is youe solution 

    I changed classes as

     [DataContract]
        public class BaseData
        {
            [DataMember]
            public  virtual int ID { get; set; }
        }
        [DataContract]
        public class SubData:BaseData 
        {
            [DataMember]
    
            public  override  int ID { get; set; }
        }
    
     and at the client side , I am getting ID property exposed for both of the classes . see the client code below. 

     Service1Client proxy = new Service1Client();
                SubData obj = new SubData();
                BaseData baseobj = new BaseData();
                obj.ID = 9;
                baseobj.ID = 10;
           
                Console.WriteLine(obj.ID);
               Console.WriteLine(baseobj.ID );
                Console.ReadKey(true);
    

    So Id for both of the classes are exposed. 

    Now coming to  your class definition 

     [DataContract(Namespace="http://localhost/KnownType")]
        [KnownType(typeof(SubData))]
        public class BaseData
        {
            [DataMember]
            public  virtual int ID { get; set; }
        }
        [DataContract(Namespace = "http://localhost/KnownType")]
        public class SubData:BaseData 
        {
            [DataMember]
    
            public  override  int ID { get; set; }
        }
    
     
    At client side both Id is exposed .

                Service1Client proxy = new Service1Client();
                SubData obj = new SubData();
                BaseData baseobj = new BaseData();
                obj.ID = 9;
                baseobj.ID = 10;
                
           
                Console.WriteLine(obj.ID);
               Console.WriteLine(baseobj.ID );
                Console.ReadKey(true);
                         
    



    Thanks Dhananjay Kumar
    My Articles on http://www.c-sharpcorner.com/Authors/AuthorDetails.aspx?AuthorID=dhananjaycoder
    Contact me at dhananjay.25july@gmail.com
    • Proposé comme réponseRahul P Nath dimanche 5 juillet 2009 11:13
    • Marqué comme réponseArefK dimanche 5 juillet 2009 11:19
    •  

Toutes les réponses

  • jeudi 2 juillet 2009 07:22Manesh_G Médailles de l'utilisateurMédailles de l'utilisateurMédailles de l'utilisateurMédailles de l'utilisateurMédailles de l'utilisateur
     

    While creating proxy it doesnot create implementation for inherited class properties .

    Other way is u can add your service reference in your client application and can accees
    your ID property from both classes instances


    Manesh
  • jeudi 2 juillet 2009 12:58ArefK Médailles de l'utilisateurMédailles de l'utilisateurMédailles de l'utilisateurMédailles de l'utilisateurMédailles de l'utilisateur
     
    Hi Manesh
    Thanks for the reply. May you please let me know what is the difference between creating a proxy and adding a WCF service reference?

    Thanks
  • jeudi 2 juillet 2009 13:30Richard BlewettMVP, ModérateurMédailles de l'utilisateurMédailles de l'utilisateurMédailles de l'utilisateurMédailles de l'utilisateurMédailles de l'utilisateur
     
    Adding a service reference generates the code for the proxy on the client side so they are basically the same thing (although creating a proxy could also mean instantiating an instance of the proxy class)

    The contract defines what data is to be passed, it doesn;t define OO semantics for the classes contract. As far as the client is concerned it has a faithful representation of the data that the service exposes. A base class with an ID and a class that derives from it
    Richard Blewett, thinktecture - http://www.dotnetconsult.co.uk/weblog2
    Twitter: richardblewett
  • jeudi 2 juillet 2009 14:18Dhananjay25 Médailles de l'utilisateurMédailles de l'utilisateurMédailles de l'utilisateurMédailles de l'utilisateurMédailles de l'utilisateur
     TraitéeA du code
    Hi AreFk, 

    See  There is no probelm in your code. It is working fine for me .  You just remove your service refernece and add it again at client.  For your better undersatding , I have pasted 4 different combinations for  your code and 3rd and 4th combination is working fine. 

    So , there is no probelem in your code 

    1. Just rebuild the service 
    2. Host it again 
    3. update serveice reference at cleint and you are done my dear friend 

    I tried out three combinations to answer you . 
    First is  I replaced [DataContract]  of base class with Serilizable attribute. And I left service implentation as same of your implentation . 

        [Serializable]
        public class BaseData
        {
            [DataMember]
            public int ID { get; set; }
        }
        [DataContract]
        public class SubData:BaseData 
        {
            [DataMember]
    
            public int ID { get; set; }
        }
    }
    
    
     Surprisngly at the client side ,  I  am getting two ID , ID1 ( I know , why I am getting two ID because , I am not overriding the ID field). But I am getting ID property exposed for the subclass .

                Service1Client proxy = new Service1Client();
                SubData obj = new SubData();
                obj.ID = 9;
                obj.ID1 = 10; 
                Console.WriteLine(obj.ID);
                Console.WriteLine(obj.ID1);
                Console.ReadKey(true);
    
    Second , when I changed the class like below 
    [Serializable]
        public class BaseData
        {
            [DataMember]
            public  virtual int ID { get; set; }
        }
        [DataContract]
        public class SubData:BaseData 
        {
            [DataMember]
    
            public  override  int ID { get; set; }
        }
    


    I am not getting ID for either of the class.  where aas I am getting Idk_backingField. I am not sure whether, it is substitution of ID property  ?

                Service1Client proxy = new Service1Client();
                SubData obj = new SubData();
                BaseData baseobj = new BaseData();
                baseobj.IDk__BackingField = 10;
                obj.IDk__BackingField = 10;
                Console.WriteLine(obj.IDk__BackingField);
               Console.WriteLine(baseobj.IDk__BackingField);
                Console.ReadKey(true);
                         
    
    3rd try which is youe solution 

    I changed classes as

     [DataContract]
        public class BaseData
        {
            [DataMember]
            public  virtual int ID { get; set; }
        }
        [DataContract]
        public class SubData:BaseData 
        {
            [DataMember]
    
            public  override  int ID { get; set; }
        }
    
     and at the client side , I am getting ID property exposed for both of the classes . see the client code below. 

     Service1Client proxy = new Service1Client();
                SubData obj = new SubData();
                BaseData baseobj = new BaseData();
                obj.ID = 9;
                baseobj.ID = 10;
           
                Console.WriteLine(obj.ID);
               Console.WriteLine(baseobj.ID );
                Console.ReadKey(true);
    

    So Id for both of the classes are exposed. 

    Now coming to  your class definition 

     [DataContract(Namespace="http://localhost/KnownType")]
        [KnownType(typeof(SubData))]
        public class BaseData
        {
            [DataMember]
            public  virtual int ID { get; set; }
        }
        [DataContract(Namespace = "http://localhost/KnownType")]
        public class SubData:BaseData 
        {
            [DataMember]
    
            public  override  int ID { get; set; }
        }
    
     
    At client side both Id is exposed .

                Service1Client proxy = new Service1Client();
                SubData obj = new SubData();
                BaseData baseobj = new BaseData();
                obj.ID = 9;
                baseobj.ID = 10;
                
           
                Console.WriteLine(obj.ID);
               Console.WriteLine(baseobj.ID );
                Console.ReadKey(true);
                         
    



    Thanks Dhananjay Kumar
    My Articles on http://www.c-sharpcorner.com/Authors/AuthorDetails.aspx?AuthorID=dhananjaycoder
    Contact me at dhananjay.25july@gmail.com
    • Proposé comme réponseRahul P Nath dimanche 5 juillet 2009 11:13
    • Marqué comme réponseArefK dimanche 5 juillet 2009 11:19
    •  
  • samedi 4 juillet 2009 04:04ArefK Médailles de l'utilisateurMédailles de l'utilisateurMédailles de l'utilisateurMédailles de l'utilisateurMédailles de l'utilisateur
     
    Hi Dhananjay25 ,
    Thank you very much for the exhaustive answer. I wrote that code within Visual Studio 2010 Beta 1 , is it possible to be a bug of VS?
    I will check that code out in  VS 2008 and will be back to you :)

    Thanks
    Aref
  • samedi 4 juillet 2009 04:31ArefK Médailles de l'utilisateurMédailles de l'utilisateurMédailles de l'utilisateurMédailles de l'utilisateurMédailles de l'utilisateur
     
    Yes, it seems to be a bug in VS2010. I checked that code with VS2008 and it works fine.

    Thank you all
  • jeudi 9 juillet 2009 12:58Dhananjay25 Médailles de l'utilisateurMédailles de l'utilisateurMédailles de l'utilisateurMédailles de l'utilisateurMédailles de l'utilisateur
     
    Have u cheked with VS2010. R u getting the same behavior
    Thanks Dhananjay Kumar
    My Articles on http://www.c-sharpcorner.com/Authors/AuthorDetails.aspx?AuthorID=dhananjaycoder
    Contact me at dhananjay.25july@gmail.com