Introduction

Understanding this article requires understanding some basics regarding WCF Services and various contracts available with the framework.

The MSDN says that a known type is an attribute class defined in the WCF Framework that allows you to specify the types that should be included for consideration during deserialization.

What the preceding statement means is that when communication happens between a WCF service and client by passing parameters and return values, both endpoints share all of the data contracts of the data to be transmitted.

Data Contracts MSDN Definition

A data contract is a formal agreement between a service and a client that abstractly describes the data to be exchanged. That is, to communicate, the client and the service do not need to share the same types, only the same data contracts. A data contract precisely defines, for each parameter or return type, what data is serialized (turned into XML) to be exchanged.

When data arrives at a receiving endpoint, the WCF runtime attempts to de-serialize the data. The type that is instantiated for deserialization is chosen by first inspecting the incoming message to determine the data contract to which the contents of the message conform.

A problem occurs when a service returns a derived type of the data contract instead of the base data contract.

Are you confused? Alright, let us create a scenario where two types of customers exist, one is a normal customer and the other is a classic customer of a customerOrder service.

Here we have a data contract of the customer that will be responsible for the transmission between the client and the service.

Now in one case when we need to return a derived class of a classic customer then WCF de-serialization does not recognize the derived data type and starts giving exceptions.

Sample WCF service

  1. namespace CustomerOrderService
  2. {
  3. [ServiceContract]
  4. public interface IOrderService
  5. {
  6. [OperationContract]
  7. Customer GetCusomersDetails(int Id);
  8. [OperationContract]
  9. void AddCustomers();
  10. }
  11. }
Data Contract (Base Class: Customer)
  1. namespace CustomerOrderService
  2. {
  3. [DataContract]
  4. public class Customer
  5. {
  6. [DataMember]
  7. public int ID { get; set; }
  8. [DataMember]
  9. public string CustomerName { get; set; }
  10. [DataMember]
  11. public string Location { get; set; }
  12. [DataMember]
  13. public string MobileNo { get; set; }
  14. public CustomerType customerType { get; set; }
  15. }
  16. [DataContract]
  17. public enum CustomerType
  18. {
  19. [EnumMember]
  20. ClaasicCustomers = 1,
  21. [EnumMember]
  22. NormalCustomers = 2
  23. }
  24. }
Derived Class:
  1. public class ClassicCustomers : Customer
  2. {
  3. public float Discount { get; set; }
  4. public int RewardPoints { get; set; }
  5. }
  6. public class NormalCustomers : Customer
  7. {
  8. public string newOffers { get; set; }
  9. }
Service Code:
  1. namespace CustomerOrderService
  2. {
  3. public class OrderService : IOrderService
  4. {
  5. public Customer GetCusomersDetails(int ID)
  6. {
  7. Customer cust = Null;
  8. string Conn = ConfigurationManager.ConnectionStrings["customerConn"].ConnectionString;
  9. using (SqlConnection myconn = new SqlConnection(Conn))
  10. {
  11. SqlCommand cmd = new SqlCommand("sp_GetCustomers", myconn);
  12. cmd.CommandType = CommandType.StoredProcedure;
  13. SqlParameter param = new SqlParameter();
  14. param.ParameterName = "@ID";
  15. param.Value = ID;
  16. cmd.Parameters.Add(param);
  17. myconn.Open();
  18. SqlDataReader reader = cmd.ExecuteReader();
  19. while (reader.Read())
  20. {
  21. cust = new ClassicCustomers()
  22. {
  23. CustomerName = Convert.ToString(reader["CustomerName"]),
  24. Location = reader["CustomerAddress"].ToString(),
  25. MobileNo = reader["MobileNo"].ToString(),
  26. RewardPoints = (int.Parse)(reader["RewardPoints"].ToString())
  27. };
  28. }
  29. }
  30. return cust;
  31. }
  32. public void AddCustomers(Customer cust)
  33. {
  34. throw new NotImplementedException();
  35. }
  36. }
  37. }
Explanation

In the above example we have a Customer Order service with Base class data contract Customer and two derived classes, normal customer and classic customer. So here our requirement is to get the customer details on the basis of the flag customer type and return derived type.

Here in the above example we are trying to return the Classic customer that is the derived type.

At the client end when the WCF Framework tries to de-serialize the data contract it does not have any knowledge of the derived type and it therefore throws exceptions.

start throwing exceptions

The WCF Framework introduced solution for this problem called the KnownTypeAttribute class.

The KnownTypeAttribute class is recognized by the DataContractSerializer when serializing or deserializing a given type, in other words the known type helps to get a derived class deserialized at the client end.
  1. [KnownType(typeof(ClassicCustomers))]
  2. [KnownType(typeof(NormalCustomers))]
  3. [DataContract]
  4. public class Customer
  5. {
  6. [DataMember]
  7. public int ID { get; set; }
  8. [DataMember]
  9. public string CustomerName { get; set; }
  10. [DataMember]
  11. public string Location { get; set; }
  12. [DataMember]
  13. public string MobileNo { get; set; }
  14. public CustomerType customerType { get; set; }
  15. }
customer detail

The receding is the output from the client using the CustomerOrderService WCF service and the RewardPoints is the property of the derived data contract Classiccustomer meaning that after using the known type attribute the DataContactSerilizer engine of WCF starts recognizing the derived data contact and does allow it to pass to the client giving the desired results.

Ways to Use KnowTypeAttribute

The WCF Framework has provided the control on using the knowtypeattribute when creating the service. The known type attribute can be provided in on of two ways.

Conclusion

The Known Type attribute is the solution to the deserialization problem of when a derived type is being used in the service.

Happy Coding and keep learning and sharing.

References

Data Contract Known Types.