Showing posts with label WCF. Show all posts
Showing posts with label WCF. Show all posts

Monday, 7 September 2015

Use of Known Type in WCF

Prerequisites

You need to be familiar with the structure of the WCF Technology and C# to better understand.

Introduction

The KnownTypeAttribute class allows you to specify, in advance, the types that should be included for consideration during deserialization.
Normally, when passing parameters and return values between a client and a service, both endpoints share all of the data contracts of the data to be transmitted.
When data arrives at a receiving endpoint, the WCF runtime attempts to deserialize the data into an instance of a common language runtime (CLR) type. 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. The deserialization engine then attempts to find a CLR type that implements a data contract compatible with the message contents. The set of candidate types that the deserialization engine allows for during this process is referred to as the deserializer's set of "known types."
One way to let the deserialization engine know about a type is by using the KnownTypeAttribute. The attribute cannot be applied to individual data members, only to whole data contract types. The attribute is applied to an outer type that can be a class or a structure. In its most basic usage, applying the attribute specifies a type as a "known type." This causes the known type to be a part of the set of known types whenever an object of the outer type or any object referred to through its members is being deserialized.

Let's Do A Practical Example to Follow

Create a new WCF Service Application and implement the following model:
[DataContract] 
public abstract class Person
 {
  [DataMember]
  public int Code { get; set; }
 
  [DataMember]
  public string Name { get; set; }
 }
[DataContract]  
public class Student : Person
 {
  [DataMember]
  public int StudentId { get; set; }
 }
[DataContract]
public class Teacher : Person
 {
  [DataMember]
  public int TeacherId { get; set; }
 } 
Suppose we want to create a service that can give us lists of all the entities in the system (include Students &Teachers). First, we define the contract in the following way:
[ServiceContract]
    public interface IStudentService
    {
        [OperationContract]
        IEnumerable<Person> GetAll();
    } 
As you can see, the output of GetAll method is Person (Base type of Student & Teacher). So the service we'll implement is in the following form:
public class StudentService : IStudentService
   {
       public IEnumerable<Person> GetAll()
       {
           List<Person> listOfPerson = new List<Person>();
 
           listOfPerson.Add( new Student() 
           { Code = 1, StudentId = 123, Name = "student 1" } );
           listOfPerson.Add( new Student() 
           { Code = 1, StudentId = 124, Name = "student 2"} );
           listOfPerson.Add( new Student() 
           { Code = 1, StudentId = 125, Name = "student 3"} );          
 
 
           listOfPerson.Add( new Teacher() 
           { Code = 2, TeacherId = 321, Name = "Mehran mousavi"} );
           listOfPerson.Add( new Teacher() 
           { Code = 2, TeacherId = 322, Name = "Teacher 2" } );
           listOfPerson.Add( new Teacher() 
           { Code = 2, TeacherId = 323, Name = "Teacher 3"} );
 
           return listOfPerson;
       }
To display the output of this WCF Service, create a new ConsoleApplication project and add this service byAddServiceReference to it.
Main function of our ConsoleApplication project is as follows:
class Program
   {
       static void Main( string[] args )
       {
           StudentService.StudentServiceClient client = 
             new StudentService.StudentServiceClient();
 
           client.GetAll().ToList().ForEach( _record => 
           {
               Console.Write( "Name : {0}", _record.Name );
               Console.WriteLine( "Code : {0}", _record.Code );
           } );
 
           Console.ReadLine();
       }
   } 
After build and run the ConsoleApplication, we get a error !!!

Why !!? The problem is that when you try to invoke the service the actual implementation returns a ChildModelfor WCF Deserialize Engine has no knowledge. The clients of the service neither have knowledge of this type.
So you need to explicitly indicate this class that you are using in the implementation but is not part of the contract. This could be done by using the KnownType attribute in base Class of Student & Teacher:
[DataContract]
 [KnownType( typeof( Student ) )]
 [KnownType( typeof(Teacher) )]
 public abstract class Person
 {
     [DataMember]
     public int Code { get; set; }
 
     [DataMember]
     public string Name { get; set; }
 } 
After changing your WCF Service, now you can run Client (ConsoleApplication) and see the result successfully ...

Friday, 28 August 2015

App Config structure in WCF


Below Nodes are there in WCF basic bidning
  1. Configuration 
  2. System.ServiceModel
  3.  Services 
  4. Service =>  Name, Behavior Configuration 
  5. endpoint => address, binding , contract 
  6. host => base address 
  7. behaviors => Service behaviors  



<configuration>
     <system.serviceModel>
         <services>
             <service name="WcfCustomerService.CustomerService"
               behaviorConfiguration = "CustomerServiceMEXBehavior" >
                 <endpoint address =""
               binding="basicHttpBinding"
               contract="WcfCustomerService.ICustomerService"/>

                 <endpoint address ="net.tcp://localhost:8090/CustomerService"
                 binding="netTcpBinding"
                 contract="WcfCustomerService.ICustomerService"/>

                 <host>
                     <baseAddresses>
                         <add baseAddress ="http://localhost:8081/CustomerService"/>
                         <add baseAddress ="net.tcp://localhost:8090/CustomerService"/>
                     </baseAddresses>
                 </host>
             </service>
         </services>
         <behaviors>
                 <serviceBehaviors>
                     <behavior name="CustomerServiceMEXBehavior" >
                         <serviceMetadata httpGetEnabled="true" />
                     </behavior>
                 </serviceBehaviors>
             </behaviors>
     </system.serviceModel>
 </configuration  >

Wednesday, 26 August 2015

Why we use MessageContract when DataContract already is there?

1. What is Data Contract?
·         Data Contracts are used to describe the data types used by a service. Interoperability is possible through this since it uses metadata of the services in background. Data Contracts can be used to describe either parameters or return values.
·         Data contracts are used to define the data structure. Messages that are simply a .NET type, let’s say lain old CLR object, and generate the XML for the data you want to pass.
·         Data Contracts describes the data types used by a service.
·          Data Contracts can be used to describe either parameters or return values.
·         Data Contracts are unnecessary if the service only uses simple types
·         Data contracts enable interoperability through the XML Schema Definition (XSD) standard.
·         Example
        Basic DataContract is defined:

1.                  [DataContract] 
2.                  public class Shape { } 
3.                   
4.                  [DataContract(Name = "Circle")] 
5.                  public class CircleType : Shape { } 
6.                   
7.                  [DataContract(Name = "Triangle")] 
8.                  public class TriangleType : Shape { } 

2. What is message contract?
·         Message contracts are preferred only when there is a need to "control" the layout of your message (the SOAP message); for instance, adding specific headers/footer/etc to a message.
·         Message contracts describe the structure of SOAP messages sent to and from a service and enable you to inspect and control most of the details in the SOAP header and body.
·         Whereas data contracts enable interoperability through the XML Schema Definition (XSD) standard, message contracts enable you to interoperate with any system that communicates through SOAP.
·         While, MessageContract(s) describes the structure of SOAP messages(since SOAP is context oriented - passing-on complete information about object) sent to/from a service and enable you to inspect and control most of the details in the SOAP header and body.
·         1. Generic - MessageContract enables you to interoperate with any system that communicates through SOAP.

2. Control - Using message contracts, we get complete control over SOAP messages sent to/from a service by having access to the SOAP headers and bodies. 3. Object Context - This(SOAPing) allows use of simple or complex types to define the exact content of the SOAP.
·         Example
Following is a simplest message contract:


[MessageContract] 
public class BankingDepositLog 
{ 
  [MessageHeader] public int numRecords 
  [MessageHeader] public DepositRecord records[]; 
  [MessageHeader] public int branchID; 
} 




Why we use MessageContract when DataContract already is there?

A very simple answer to the question is, when you need a higher level of control over the message, such as sending custom SOAP header, you then use MessageContract instead of DataContract. But in my opinion, most of the messaging needs can be catered by DataContracts.
Sometimes complete control over the structure of a SOAP message is just as important as control over its contents. This is especially true when interoperability is important or to specifically control security issues at the level of the message or message part. In these cases, you can create a message contract that enables you to use a type for a parameter or return value that serializes directly into the precise SOAP message that you need.
why it is useful to use MessageContract(s), that is, to pass information in SOAP headers, you will have to dive into the SOAP advantages

We Can’t Mix Data and Message contract
Most important thing is we can’t mix Data and Message contract Because message-based programming and parameter-based programming cannot be mixed, so you cannot specify a DataContract as an input argument to an operation and have it return a MessageContract, or specify a MessageContract as the input argument to an operation and have it return a DataContract. You can mix typed and untyped messages, but not messageContracts and DataContracts. Mixing message and data contracts will cause a runtime error when you generate WSDL from the service.

Answer is


When we need a higher level of control over the message, such as sending custom SOAP header, then we can useMessageContract instead of DataContract . But in general cases, most of the messaging needs can be fulfilled by DataContracts.

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.