What's New in Windows Communication Foundation (WCF) 4.0 Part III - Service-Discovery Feature
The concept of WS-Discovery defines SOAP-based protocol; this protocol helps for discovering the location endpoints of the service at runtime. The client application uses this protocol to probe the service endpoints and then using this endpoint address, the communication is established with the WCF service. Ad-Hoc mode and Managed mode are the modes used by WS-Discovery.
In this article, we will see the Ad-Hoc mode of WS-Discovery. In an Ad-Hoc mode, the client applications discover WCF service by sending multicast messages.
Task 1: Creating WCF service.
Let us create a WCF service.
Step 1: Open VS 2010 and create a blank solution, name this as ‘WCF_DiscoveryApplication’. In this solution add a new WCF service library project, name this as ‘WCF_ServiceFor_AdHoc_Discovery’.
Step 2: Remove App.Config file from this project. Rename ‘IService1.cs’ to ‘IService.cs’, rename ‘Service1.cs’ to ‘CService.cs’.
Step 3: In the service project add the reference to ‘System.ServiceModel.Discovery’. This namespace provides access of discovery classes.
Step 4: Write the following code in ‘Iservice.cs’
C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
namespace WCF_ServiceFor_AdHoc_Discovery
{
[ServiceContract]
public interface IService
{
[OperationContract]
string GetData(int value);
}
}
VB.NET
Imports System
Imports System.Collections.Generic
Imports System.Linq
Imports System.Runtime.Serialization
Imports System.ServiceModel
Imports System.ServiceModel.Web
Imports System.Text
Namespace WCF_ServiceFor_AdHoc_Discovery
<ServiceContract> _
Public Interface IService
<OperationContract> _
Function GetData(ByVal value As Integer) As String
End Interface
End Namespace
Step 5: Implement this interface in ‘CService’ class as below:
C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
namespace WCF_ServiceFor_AdHoc_Discovery
{
public class CService : IService
{
public string GetData(int value)
{
return string.Format("You entered: {0}", value);
}
}
}
VB.NET
Imports System
Imports System.Collections.Generic
Imports System.Linq
Imports System.Runtime.Serialization
Imports System.ServiceModel
Imports System.ServiceModel.Web
Imports System.Text
Namespace WCF_ServiceFor_AdHoc_Discovery
Public Class CService
Implements IService
Public Function GetData(ByVal value As Integer) As String
Return String.Format("You entered: {0}", value)
End Function
End Class
End Namespace
Step 6: Build the project and make sure that there are no build errors.
Task 2: Writing Host for the Service.
Step 1: To the solution, add a new console application, name this as ‘WCF_AdHocDiscoveryHost’.
Step 2: Add a reference to ‘System.ServiceModel’ and ‘System.ServiceModel.DIscovery’ in this project.
Step 3: In the project add a new ‘App.Config’ file and write the following configuration:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<services>
<service name="WCF_ServiceFor_AdHoc_Discovery.CService"
behaviorConfiguration="ServBehave">
<host>
<baseAddresses>
<add baseAddress = "http://localhost:5661/WCFDiscoveryService" />
</baseAddresses>
</host>
<endpoint address ="" binding="wsHttpBinding"
contract="WCF_ServiceFor_AdHoc_Discovery.IService">
</endpoint>
<!--Standard UDP Discovery Endpoint-->
<endpoint name="udpDiscovery" kind="udpDiscoveryEndpoint"></endpoint>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="ServBehave">
<serviceMetadata httpGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="False" />
<serviceDiscovery/>
<!--This Enables Service Discovery Behavior-->
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
In the above config file, ‘<serviceDiscovery>’, enables service discovery behavior. This also defines standard ‘udp’ discovery endpoints. The above ‘UDPEndpoint’ configuration makes the service discoverable over a local subnet.
Step 4: In the ‘Program.cs’ write the following code.
C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
namespace WCF_AdHocDiscoveryHost
{
class Program
{
static void Main(string[] args)
{
ServiceHost Host = new ServiceHost(typeof(WCF_ServiceFor_AdHoc_Discovery.CService));
Host.Open();
Console.WriteLine("Service Started....");
Console.ReadLine();
Host.Close();
Console.ReadLine();
}
}
}
VB.NET
Imports System
Imports System.Collections.Generic
Imports System.Linq
Imports System.Text
Imports System.ServiceModel
Namespace WCF_AdHocDiscoveryHost
Friend Class Program
Shared Sub Main(ByVal args() As String)
Dim Host As New ServiceHost(GetType(WCF_ServiceFor_AdHoc_Discovery.CService))
Host.Open()
Console.WriteLine("Service Started....")
Console.ReadLine()
Host.Close()
Console.ReadLine()
End Sub
End Class
End Namespace
Step 5: Build the solution and make sure that it is error free.
Task 3: Creating Client Application.
Step 1: Now to the solution, add a new console project and name it as ‘ConsoleClient_WCFDiscoveryService_AdHoc’. In this project add a reference to ‘System.ServiceModel.Discovery’.
Step 2: In this client, add a service reference to the WCF service project. This will create the ‘App.Config’ file and the Service proxy.
Step 3: Open ‘App.Config’ and delete the code which gets added by the ‘Add Service Reference’. Write the following new configuration in ‘App.Config’:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<client>
<endpoint
binding="wsHttpBinding"
contract="MyRef.IService" name="ClientEdp">
</endpoint>
<endpoint name="udpDiscoveryEndpoint" kind="udpDiscoveryEndpoint"></endpoint>
</client>
</system.serviceModel>
</configuration>
The above configuration defines endpoint having contract from the proxy. The other endpoint helps in discovering the address by the client application.
Step 4: In the ‘Program.cs’ of the client application write the following code:
C#
using System.Text;
using System.ServiceModel.Discovery;
using System.ServiceModel;
namespace ConsoleClient_WCFDiscoveryService_AdHoc
{
class Program
{
static void Main(string[] args)
{
string opt = "y";
while (opt == "y")
{
Console.WriteLine("Press any key when service is ready:");
Console.ReadLine();
#region Code For Discovery
//Step 1: Create a DiscoveryClient
DiscoveryClient discClient = new DiscoveryClient("udpDiscoveryEndpoint");
//Step 2: Now Search for the Contract using 'FindCriteria'
FindCriteria fCriteria = new FindCriteria(typeof(MyRef.IService));
FindResponse fResponse = discClient.Find(fCriteria);
EndpointAddress address = fResponse.Endpoints[0].Address;
#endregion
//Step 3 :Create the Proxy object
MyRef.ServiceClient Proxy = new ConsoleClient_WCFDiscoveryService_AdHoc.MyRef.ServiceClient("ClientEdp");
//Step 4: Associate the discovered Endpoint Address with Proxy
Proxy.Endpoint.Address = address;
Console.WriteLine("The discovered address is {0} on which method is called", address);
Console.WriteLine("Res = " + Proxy.GetData(1000));
Console.WriteLine("COntinte ?");
opt = Console.ReadLine();
}
Console.ReadLine();
}
}
}
VB.NET
Imports System.Text
Imports System.ServiceModel.Discovery
Imports System.ServiceModel
Namespace ConsoleClient_WCFDiscoveryService_AdHoc
Friend Class Program
Shared Sub Main(ByVal args() As String)
Dim opt As String = "y"
Do While opt = "y"
Console.WriteLine("Press any key when service is ready:")
Console.ReadLine()
' #Region "Code For Discovery"
'Step 1: Create a DiscoveryClient
Dim discClient As New DiscoveryClient("udpDiscoveryEndpoint")
'Step 2: Now Search for the Contract using 'FindCriteria'
Dim fCriteria As New FindCriteria(GetType(MyRef.IService))
Dim fResponse As FindResponse = discClient.Find(fCriteria)
Dim address As EndpointAddress = fResponse.Endpoints(0).Address
' #End Region
'Step 3 :Create the Proxy object
Dim Proxy As MyRef.ServiceClient = New ConsoleClient_WCFDiscoveryService_AdHoc.MyRef.ServiceClient("ClientEdp")
'Step 4: Associate the discovered Endpoint Address with Proxy
Proxy.Endpoint.Address = address
Console.WriteLine("The discovered address is {0} on which method is called", address)
Console.WriteLine("Res = " & Proxy.GetData(1000))
Console.WriteLine("COntinte ?")
opt = Console.ReadLine()
Loop
Console.ReadLine()
End Sub
End Class
End Namespace
The code shown is very important and here's the explanation:
1. DiscoveryClient: Allows client application to use available services. This uses udp discovery endpoint name to discover endpoint of the service.
2. FindCriteria: Represent criteria used for searching services. The criteria can be the service contract made available in the proxy.
3. FindResponse: This contains response from the find service.
Step 5: Run the application and you will get the following output:
Conclusion: WCF Discovery is one of the best feature provided in WCF 4.0. Using this mechanism, client application can dynamically discover endpoint addresses and make a call to WCF Service. Cool!
The entire source code of this article can be downloaded over here