Discovery Find and FindCriteria

A Discovery Find is initiated by a client in order to discover one or more services, and is one of the main actions in Discovery. Performing a Find sends a WS-Discovery Probe message over the network. Matching services reply with WS-Discovery ProbeMatch messages (Read more about WS-Discovery messages in the specification). Let's look at a few of the classes in .Net Framework 4 which you can use when doing a Discovery Find operation.



The DiscoveryClient class makes performing discovery client operations easy. It contains a Find() method, which performs a (blocking) synchronous find, and a FindAsync() method, which initiates a non-blocking asynchronous find. Both methods take a FindCriteria parameter, and provide results to the user through a FindResponse object.


FindCriteria has several properties, which can be grouped into search criteria (specifying what services you’re looking for) and find termination criteria (how long the search should last).


Search Criteria:

· ContractTypeNames – Optional. The contract name of the service being searched for, and the criteria typically used when searching for a service.

If more than one contract name is specified, only service endpoints matching ALL contracts will reply. Note that in WCF, an endpoint can only support one contract.


· Scopes – Optional. Scopes are absolute URIs which are used to categorize individual service endpoints.     


      Let's take an example to understand Scopes better. Suppose there are multiple printers in different levels of a building. A user in the first level who wants to search for a printer would prefer to find a one which is present in the same level. If he searches using only the contract then all the printers will respond back. To futher fine tune the responses, the user can decorate the endpoints of the Printers using scopes. The user can then specify the scopes as part of the FindCriteria and only services that have endpoints which match the scopes will respond. Another example could be where there is one single service with two (or multiple) endpoints. One endpoint could be an external facing BasicHttpBinding endpoint and the other could be an internal facing NetTcpBinding endpoint. The user can decorate these endpoints with appropriate scopes to categorize them.


If more than one scope is specified, only service endpoints matching ALL scopes will reply.


· ScopeMatchBy – ScopeMatchBy specify the matching algorithm to use while matching the scopes in the Probe message with that of the endpoint


There are five supported scope-matching rules, as described in the MSDN documentation. If you do not specify a scope-matching rule, FindCriteria.ScopeMatchByPrefix is used.

FindCriteria.ScopeMatchByExact does a basic case-sensitive string comparison.

FindCriteria.ScopeMatchByPrefix does matching by segments separated by "/". So a search for http://microsoft/building1 will match a service with scope http://microsoft/building1/floor1. Note that it won't match http://microsoft/building100, because the last two segments don't match.

FindCriteria.ScopeMatchByLdap does segment matching using an LDAP URL.

FindCriteria.ScopeMatchByUuid does exact matching for a UUID string.

FindCriteria.ScopeMatchByNone will only match services which don't have any scope specified.


It is also possible to specify custom ScopeMatchBy rule, but only custom services which support the type will respond. More on how to implement custom scope-matching in a future post.


Note: A Find using an empty FindCriteria (with no search criteria specified) will match all services listening on the network.


Termination Criteria:

· Duration – The maximum time to wait for replies from services on the network. The default duration is 20 seconds.

· MaxResults – The maximum number of replies to wait for. If MaxResults replies are received before Duration has elapsed, the Find will end. The default MaxResults is int.MaxValue.


FindResponse has an Endpoints collection property which contains any replies sent by matching services on the network. If no services replied, the collection will be empty. If one or more services replied, each reply will be stored in an EndpointDiscoveryMetadata object, which contains the address, contract, and some additional information about the service.



Here's how it all looks in a snippet of code:

// Create DiscoveryClient

DiscoveryClient discoveryClient = new DiscoveryClient(new UdpDiscoveryEndpoint());

// Create FindCriteria

FindCriteria findCriteria = new FindCriteria(typeof(IPrinterService));

findCriteria.Scopes.Add(new Uri(""));

findCriteria.Duration = TimeSpan.FromSeconds(10);

// Find ICalculatorService endpoints

FindResponse findResponse = discoveryClient.Find(findCriteria);

Console.WriteLine("Found {0} ICalculatorService endpoint(s).", findResponse.Endpoints.Count)