Friday, 21 August 2015

KnownType Attribute and How to Use It in WCF

Introduction
Data Contract describes the type of data that will be sent or received between a service and a client. But in certain scenarios, sent or received data is not known between the communicating parties. For example, a service sending data back to client is not the actual data contract but a derived type of it. In such cases, there will be a de-serialization problem. De-serialization engine will not recognize the derived Data Contract type and will generate an error.
In order to handle such scenarios, Data Contract Known types are available in Windows Communication Foundation. So by definition, "Known Type in WCF is an acceptable derived type for a Data Contract".
In one of my previous WCF Service articles, I explained WCF KnowTypeAttribute with the help of a simple example. But here in this WCF Tutorial, I'll try to discuss all possible ways to use Data Contract Known Types, so that the reader can get a detailed understanding about Known Types and be able to use it in various practical scenarios.
Consider we have a service contract "IVehicleService" as:
Hide   Copy Code
[ServiceContract]
public Interface IVehicleService
{
     [OperationContract]
     Vehicle AddNewVehicle(Vehicle myVehicle);

     [OperationContract]
     bool UpdateVehicle(Vehicle myVehicle); 
}
We can use Data Contract Known Types at different levels depending upon the requirements:
·         Global Level
o    Using Code at base type
o    Using Web.config
·         Service Contract Level
·         Operation Contract Level
Using Globally (Using Code at base type)
In order to use globally, we can apply KnownTypeAttribute at base Data Contract type as used in the following example:
Hide   Copy Code
[KnownType(typeof(Car))]
[KnownType(typeof(Truck))]
[DataContract]
public class Vehicle
{
}

[DataContract]
public class Car : Vehicle
{
}

[DataContract]
public class Truck : Vehicle
{
}
In the above example, you can see that KnownTypeAttribute is used at base Data Contract Type, i.e.,Vehicle. So, now these derived types are globally known for all service and operation contracts wherever theVehicle type is used.
Using Globally (Using Web.config)
We can achieve the same as above using web.config as follows:
Hide   Copy Code
<system.runtime.serialization>
     <dataContractSerializer>
                  <declaredTypes>
                             <add type="MyService.Vehicle,
                                                MyService, Version=<version here>,
                                                Culture=Neutral, PublicKeyToken=null">
                                         <knownType type="MyService.Car,
                                                MyService, Version=<version here>,
                                                Culture=Neutral, PublicKeyToken=null" />
                                         <knownType type="MyService.Truck,
                                                MyService, Version=<version here>,
                                                Culture=Neutral, PublicKeyToken=null" />
                            </add>
                  </declaredTypes>
     </dataContractSerializer>
</system.runtime.serialization>
The above configuration will also make the derived types (Car, Truck) as globally known Types.
Using at Service Contract
For certain scenarios, if we wanted to make such derived types as known types for a particular service, we can apply ServiceKnownTypeAttribute as follows:
Hide   Copy Code
[ServiceKnownType(typeof(Car))]
[ServiceKnownType(typeof(Truck))]

[ServiceContract]
public Interface IVehicleService
{
     [OperationContract]
     Vehicle AddNewVehicle(Vehicle myVehicle);

     [OperationContract]
     bool UpdateVehicle(Vehicle myVehicle); 
}
Now, these derived types are known to all operation contracts within IVehicleService.
Using at Operation Contract
In order to make it more restricted, i.e., for only a specific operation contract within a service, we can do the following:
Hide   Copy Code
[ServiceContract]

public Interface IVehicleService
{
      [ServiceKnownType(typeof(Car))]
      [ServiceKnownType(typeof(Truck))]
      [OperationContract]
      Vehicle AddNewVehicle(Vehicle myVehicle);

      [OperationContract]
      bool UpdateVehicle(Vehicle myVehicle); 
}
So now, these derived types are known types only for AddNewVehicle method and not for the UpdateVehicleor other operations within IVehicleService.
This Service tutorial provides all possible ways for associating Data Contract Known Types in WCF.


No comments:

Post a Comment