Friday, January 24, 2014

WCF 4.0 Features

New Features in WCF 4.0


This article describes the new Features of WCF 4.0





I will be covering in this article
  1. Dynamic WCF  Service and End Point discovery. 
  2. Intermediate Routing Pattern. 
  3. Discovery announcement.

1. Dynamic WCF  Service and End Point discovery



It allows us to Discover what Services are running and their location. It sends Hello announcement on initialization and Bye when removed from Network. Discovery API provided by WCF helps Client to find service on the network by using Discovey Standard or protocol. Client can send multicast Probe message to discover service to which Service can reply with Probe match message which contains information to  connect to service.For Services that have changed Endpoint Resolve message can be sent to which Service can respond with ResolveMatch message.
Discovery API Modes-

1. Managed Mode - Discovery Proxy is the Central Server which Services use to publish themselves and Client use to get information. This is done by Announcement message to Discovery Proxy so that all Clients  can know all the Services that are up and running. Client sends Probe message to which  Server responds with Probe match

2. Ad-Hoc Mode - No Central Server. All announcement and request are done via Multicast. Clients have to listen for these announcements. Client even sends Probe message via multicast.

Following is the config file for  WCF Service-
<system.serviceModel>
    <services>
      <service name="WcfService1.Service1" behaviorConfiguration="WcfService1.Service1Behavior">
        <!-- Service Endpoints -->
        <endpoint address="" binding="wsHttpBinding" contract="WcfService1.IService1">
          <!--
  Upon deployment, the following identity element should be removed or replaced to reflect the
  identity under which the deployed service runs.  If removed, WCF will infer an appropriate identity
  automatically.
  -->
          <identity>
            <dns value="localhost"/>
          </identity>
        </endpoint>
        <endpoint name ="udpDiscovery" kind ="udpDiscoveryEndpoint" />
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
      </service>
        </services>
 
    <behaviors>
      <serviceBehaviors>
        <behavior name="WcfService1.Service1Behavior">
          <!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
          <serviceMetadata httpGetEnabled="true"/>
          <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
          <serviceDebug includeExceptionDetailInFaults="false"/>
          <serviceDiscovery />
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>

With this configuration we enable service and Endpoint discovery for our service. Here we use a new feature of WCF4 called standard endpoints (by using  the "kind" attribute on the udpDiscovery endpoint).

If Client wants to talk to a service which supports endpoints for IService1 we  can use  client-side discovery API like this:

DiscoveryClient discoverclient = new DiscoveryClient(new UdpDiscoveryEndpoint()); 
  FindResponse response = discoverclient.Find(new FindCriteria(typeof(IService1))); 
 EndpointAddress address = response.Endpoints[0].Address; 
  Service1Client client = new Service1Client(new  WSHttpBinding(), address); 
  string str= client.CheckMessage("Hello Testing Dynamic Service and EndPoint Discovery in  WCF 4 ."); 
  Console.WriteLine(str); 
But what if the Binding changes?

For this We can pass a MEX (MetadataExchange, based on WS-MetadataExchange) address to the static Resolve method.

<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>


2. Intermediate Routing Pattern

We have  one service entry point with a universal contract and we  route incoming messages to the corresponding  business services.



We use System.ServiceModel.Routing.RoutingService..Generic routing service in WCF4  enables routing for different message exchange patterns .We implement routing service by using Message Filters.

Hosting Routing Service

ServiceHost serviceHost = new ServiceHost(typeof(RoutingService));
            try
            {
                serviceHost.Open();
                Console.ReadLine();
                serviceHost.Close();
            }
            catch (CommunicationException)
            {
                serviceHost.Abort();
            }

 

Routing Service by Message Filters
<configuration>

<system.serviceModel>

<services>

<service behaviorConfiguration="routingData" name="System.ServiceModel.Routing.RoutingService">

<host>

<baseAddresses>

<add baseAddress="http://localhost/Services/WCFSample"/>

</baseAddresses>

</host>

<endpoint address="" binding="basicHttpBinding" name="requestReplyEndpoint" contract="System.ServiceModel.Routing.IRequestReplyRouter"/>

</service>

</services>

<behaviors>

<serviceBehaviors>

<behavior name="routingData">

<serviceMetadata httpGetEnabled="True"/>

<routing filterTableName="mainRoutingTable"/>

</behavior>

</serviceBehaviors>

</behaviors>

<client>

<endpoint name="TestService" address="http://localhost:8080/Services/TestWCFSample" binding="basicHttpBinding" contract="*"/>

</client>

<routing>

<filters>

<filter name="MatchAllFilter" filterType="MatchAll"/>

</filters>

<filterTables >

<filterTable name="mainRoutingTable">

<add filterName="MatchAllFilter" endpointName="IntermediateRoutingSample"/>

</filterTable>

</filterTables>

</routing>

</system.serviceModel>

<system.web>

<compilation debug="true"/></system.web></configuration>




































 Here we are exposing  IRequestReplyRouter at  http://localhost:8080/Services/WCFSample to the consumers. Based on the message filter in the entry in the routing table, the messages received by the service will be sent to the endpoint . Client side-
<configuration>

<system.serviceModel>

<client>

<endpoint address="http://localhost:8080/Services/WCFSample"

binding="basicHttpBinding"

contract="IHelloService" />

</client>

</system.serviceModel>

</configuration>





















 

 

 

 

 

 

 

3. Discovery Announcement



 
 This shows when my Service is Online or Offline. This is done by Announcement Endpoint. This allows Clients who are listening to learn about new services. This reduces the amount of Probing/Multicast messaging.

    

We can configure a service with an announcement endpoint by using the <serviceDiscovery> behavior. The <serviceDiscovery> behavior allows us to define a collection of announcement endpoints that will be exposed by the service. We can use the standard “udpAnnouncementEndpoint” .

We  also  need to configure the service with a standard “udpDiscoveryEndpoint” if we want it to respond to discovery probes initiated by clients. The following example shows a typical configuration:
<configuration>

<system.serviceModel>

<services>

<service name="WcfService1"

 behaviorConfiguration="serviceBehavior">

 <endpoint address=""

binding="basicHttpBinding"

contract="IService1" />

<endpoint name="udpDiscovery" kind="udpDiscoveryEndpoint"/>

</service>

</services>

<behaviors>

<serviceBehaviors>
 

<behavior name="serviceBehavior">

<serviceDiscovery>

<announcementEndpoints>

<endpoint name="udpAnnouncement" kind="udpAnnouncementEndpoint"/>

</announcementEndpoints>

</serviceDiscovery>

</behavior>

</serviceBehaviors>

</behaviors>

</system.serviceModel>

</configuration
With this configuration , the service will announce  when it comes online and it will also announce when it’s going offline. W’ll have to specifically design  clients to listen for them at runtime. We can  do this by hosting an announcement service in client application that uses  WS-Discovery announcement protocol.
WCF 4 comes with a class called AnnouncementService designed  for this purpose. The AnnouncementService provides two event handlers:
1. OnlineAnnouncementReceived 
2. OfflineAnnouncementReceived.
 Client applications can simply host an instance of the AnnouncementService using ServiceHost and register event handlers for these two events.
Whenever a service comes online and announces itself, the client-hosted AnnouncementService will receive the “online” announcement and OnlineAnnouncementReceived will fire in the client. When the service goes offline, it will send an “offline” announcement and OfflineAnnouncementReceived will fire in the client.

Here I will cover

        •  Simplified Configuration
        •  Protocol bridging and Fault tolerance
        •  Standard End Points.
        •  .svc-less activation of REST services or making REST URI nice.



1. Simplified Configuration



In WCF 3.5 when we host  Service without  Endpoint we get  exception saying that we need to configure at least a single Endpoint.   But in WCF 4.0 this is not the case because Service Runtime will automatically adds default endpoints for us.
Lets see how this works –
Code for IService1-
[ServiceContract]
    public interface IService1
    {
        [OperationContract]
        string GetData(int value);
    }
Code for Service1 -
public string GetData(int value)
        {
            return string.Format("You entered: {0}", value);
        }
 
Now add ConsoleApplication1 in the Solution.
Add following in App.config.
<system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <serviceMetadata httpGetEnabled ="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <protocolMapping>
      <add binding="wsHttpBinding" scheme ="http"/>
    </protocolMapping>
  </system.serviceModel>
Add the following code in Program.cs-
static void Main(string[] args)
        {
            ServiceHost Host = new ServiceHost(typeof(WcfSimpleService1.Service1), new Uri("http://localhost:7777/Services/Hello"));
            Host.Open();
            Console.WriteLine("Wow Started....");
            Console.ReadLine();
            Host.Close();
            Console.ReadLine();
        }
Put breakpoint on Host.Open and run ConsoleApplication.Since protocol mapping is set to wsHttpBinding it uses wsHttpBinding as shown in fig-

 

You can also download the attached project file.
2. Protocol bridging and Fault tolerance
Protocol bridging is basically used for transport. As in fig.  Client sends message to Routing Service via HTTP .Routing Service will send the message to Backend WCF Service via TCP/IP.Here we are using Protocol bridging between HTTP AND TCP/IP.
Fault tolerance is alternate endpoints (any no of endpoints) which will  be called when Exception occurs in the RoutingService while calling the original target endpoint.

We are  exposing  our RoutingService via an basicHttpBinding-based request-reply endpoint.
      <service behaviorConfiguration="routingData"
    name="System.ServiceModel.Routing.RoutingService">
        <host>
          <baseAddresses>
            <add  baseAddress="http://localhost:3562/Services/Hello"/>
          </baseAddresses>
        </host>
        <endpoint address=""
                  binding="basicHttpBinding"
                  name="requestReplyEndpoint"
                  contract="System.ServiceModel.Routing.IRequestReplyRouter" />
      </service>

We have actually two services TestService1 and TestService2.One is exposed via basicHttpBinding and other through netTcpBinding.
We have configured our router in such a way that it still accepts incoming messages via basicHttpBinding  but on need arising it  can route messages to the netTcpBinding-based service.
  <client>
        <endpoint name="TestService1"
                  address="net.tcp://localhost:3562/Services/Test"
                  binding="netTcpBinding"
                  contract="*" />
        <endpoint name="TestService2"
                  address="http://localhost:3562/Services/Test"
                  binding="basicHttpBinding"
                  contract="*" />
  </client>
Routing table to route to netTcpBinding-based service.
<routingTables>
        <table name="mainRoutingTable">
          <entries>
            <add filterName="xPath1" endpointName="TestService1" />
          </entries>
        </table>
</routingTables>
We can specify alternate endpoints (any no of endpoints) which will  be called when Exception occurs in the RoutingService while calling the original target endpoint.

<routingTables>
        <table name="mainRoutingTable">
          <entries>
            <add filterName="xPath1" endpointName="TestService1"                         alternateEndpoints="endpointsList" />
          </entries>
        </table>
  </routingTables>
  <alternateEndpoints>
        <list name="endpointsList">
          <endpoints>
            <add endpointName="TestService2" />
            </endpoints>
        </list>
  </alternateEndpoints>
Here we have TestService2 endpoint which is exposed via  basicHttpBinding endpoint.

3. Standard End Points



Standard endpoints(For this use kind attribute ) enable a developer to define an endpoint that has default values . These endpoints allow  to use  an endpoint without  specifying information of a static nature. Standard endpoints can be used for infrastructure and application endpoints. Standard endpoints  exposes your service for metadata exchange. Same result can be accomplished by using the “mexEndpoint” standard endpoint as follows:


<system.serviceModel>
    <services>
      <service name="HelloService">
        <endpoint kind="udpDiscoveryEndpoint" />
      </service>
    </services>
    <behaviors>
      <behavior>
        <serviceDiscovery />
      </behavior>
    </behaviors>
  </system.serviceModel>

 


We can also  specify a reusable endpointConfiguration for the endpoint using the new standardEndpoints section in Web.config

 
<system.serviceModel>
    <services>
      <service name="TestService">
        <endpoint
            kind="udpDiscoveryEndpoint"
            endpointConfiguration="udpDiscoveryEndpointSettings"/>
      </service>
    </services>
    <standardEndpoints>
      <udpDiscoveryEndpoint>
        <standardEndpoint
          name="udpDiscoveryEndpointSettings"
          multicastAddress="soap.udp://239.255.255.252:5762"
          maxResponseDelay="00:00:07">
          <transportSettings
              duplicateMessageHistoryLength="2048"
              maxPendingMessageCount="5"
              maxReceivedMessageSize="8192"
              maxBufferPoolSize="262144"/>
        </standardEndpoint>
      </udpDiscoveryEndpoint>
    </standardEndpoints>
    <behaviors>
      <behavior>
        <serviceDiscovery />
      </behavior>
    </behaviors>
  </system.serviceModel>

4. .svc-less activation of REST services.

It is specially needed in  WAS-hosting WCF services.If we have to write  http://xyz/ CalulatorService.svc .svc at the end of url makes it user unfriendly. It also makes it Low REST service as it does not follows REST URI principle.
Till date developers have to overcome this limitation by implementing URL ReWrite module in IIS. WCF 4.0 has introduced a feature to access WCF services using attribute called as relativeAddress.
<system.serviceModel>
    <serviceHostingEnvironment>
      <serviceActivations>
        <add relativeAddress="/Calculator" service="CalulatorService.svc"/>
      </serviceActivations>
    </serviceHostingEnvironment>
  </system.serviceModel>
Now  we can write http://xyz/CalulatorService.  
Neat isn’t it.




No comments:

Post a Comment