New Features in WCF 4.0
This article describes the new Features of WCF 4.0
I will be covering in this article
- Dynamic WCF Service and End Point discovery.
- Intermediate Routing Pattern.
- 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.
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();
}
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"><endpointkind="udpDiscoveryEndpoint"endpointConfiguration="udpDiscoveryEndpointSettings"/></service></services><standardEndpoints><udpDiscoveryEndpoint><standardEndpointname="udpDiscoveryEndpointSettings"multicastAddress="soap.udp://239.255.255.252:5762"maxResponseDelay="00:00:07"><transportSettingsduplicateMessageHistoryLength="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>
Neat isn’t it.
No comments:
Post a Comment