Web services have been around for over 10 years now in some form or fashion. What this means is that there are millions of services in existence, on the public internet as well as your private network, and they mostly all lack at least one thing in common, discovery. Discovery is the mechanism by which web services and clients can be made aware of other web services and clients on a network. Discovery comes in two basic designs. One design pattern is where a client or service queries a central repository for registered services to find and discover details about it. Another design pattern is based on broadcasting and notification, where a special protocol is used to announce a client or service’s joining and leaving the network.
When developing web services with the Microsoft technology stack, Microsoft first introduced the Soap toolkit. Afterwards, ASP.NET ASMX was created to quickly build web services, following that the WSE extensions, and finally as its most current technology Windows Communication Foundation with version 4.0 of the .Net 4.0 Framework. WCF and .Net 4.0 Framework brings some interesting new features to the table, one in particular deals with web service Discovery using the WS-Discovery standard. This new standard takes the broadcasting and announcement design pattern to discovery.
How Discovery Worked Prior to Today
Prior to this version of WCF, the only supported discovery mechanism, was the querying of a central repository, usually UDDI sometimes through a class called the Metadata Resolver, but mostly through the UDDI API classes and methods. UDDI provided a central registry to store information about available services. It supplied a catalog where clients and services could find services that meet their needs. It is more similar to a yellow-page phonebook directory of information allowing the client or service to find other services by name, address, contract, category, or by other metadata. UDDI can be thought of as a very poor implementation of DNS for Web services.
Needless to say, the UDDI API stack never really made headlines. The reason being the API was far too complex, and it’s development model was too clunky to fit the Web Service executing platform, and no-one except the inventors of UDDI, understood tModels especially if all you wanted was a url to a service named “OrdersService”. What I mean by this is that Web Services were based off the HTTP protocol, with SOAP additions in a stateless model. While UDDI was created on the HTTP protocol, and using SOAP, UDDI implementations were too clunky and dealt more with the Business, and business model than with the actual service to really make an impact on the web service technology space. For example, to retrieve the details you were looking for, you needed to create multiple tModels, tModelRequests and parse through multiple tModelResponses just to get to the specific information being requested, instead of “1 simple query call, that’s all.”
I digress, a little. There was nothing wrong with the query Design pattern, just the UDDI implementation. We at Tellago Studios, believe that the query design pattern has its benefits as long as the implementation follows more of a web service, SOA centric perception of a central repository. SO-Aware does just that. It provides a SOA Centric RESTful implementation to query a central repository. If you want the Url of a registered service, just query it using OData. However, SO-Aware doesn’t stop there. Because of it’s RESTful implementation, I will show in this two part article posting how SO-Aware can also take advantage of both the querying and the second design pattern: broadcast and announcements, using the WS-Discovery protocol and WCF 4.0. Part 1 of this article continues to talk about querying a central repository, whereas part two discusses WCF 4.0 and the WS-Discovery mechanism and how SO-Aware can be leveraged with it. (Read Part 2 here)
How SO-Aware Handles Querying the SO-Aware Service Repository
Let’s first tackle the first design pattern for discovery, which is querying a central repository. SO-Aware provides its own Service metadata Repository, and contains a set of classes for both a Client and Service to use for querying it, as well as the core WCF Data Service: SO-Aware Service Repository which uses the OData protocol to query directly. (To see more information on these classes and the core Service Repository view our videos on Server Side API parts 1 and 2 along with the Client Side API parts 1 and 2). To keep in tune with the querying the central repository, I’ll focus on the client side classes for this post and handle the server side querying in another post.
To query the central repository on the client SO-Aware provides two classes, ConfigurableProxyFactory and ConfigurationResolver. These classes can be found inside the Tellago.ServiceModel.Governance.ServiceConfiguraion.dll assembly.
To borrow from the documentation: The ConfigurableProxyFactory class is used to configure a client proxy for communicating with the SO-Aware Service Repository to retrieve configuration, behavior and binding information. It is meant to be used within client source code for dynamically resolving configuration information. Behind the scenes it uses the WCF ChannelFactory class to create WCF Communication objects through channels for sending and receiving queries and responses. The steps to use this class are simple:
- Create an instance of this class in the Client / Service application
- Inside the constructor set the SO-Aware Configuration query
- Create a WCF Channel based on the service contract interface expected for communication.
- Invoke your service operations, you’re done.
Here’s a code example:
ConfigurableProxyFactory<ISampleService> factory = new ConfigurableProxyFactory<ISampleService>(new Uri(http://localhost:8088/SO-Aware/ServiceRepository.svc “), “SampleService(1.0)”, null);
ISampleService service = factory.CreateProxy();
var response = service.DoOperation(dataToService);
Using the ConfigurationResolver class is just as simple. This class is used to manually resolve SO-Aware Service Repository Bindings, Endpoints, and Endpoint Behaviors. This class is meant to be used within a client or service source code for dynamically and manually resolving configuration information. The Steps to use this class are:
- Determine which WCF component is needed for communication: Binding, Endpoint, or Endpoint Behavior.
- Create an instance of the ConfiguationResolver class.
- Manually create any supporting WCF components for communication such as Addresses, Bindings, Endpoints and Contracts, depending on what components you already have.
- Invoke the ConfigurationResolver.Resolve*() methods to retrieve Bindings, Endpoint information such as EndpointAddress, Contracts, and Behaviors and let SO-Aware create the rest of the components for you.
Here’s a code example:
ConfigurationResolver resolver = new ConfigurationResolver(“http://localhost:8088/SO-Aware/ServiceRepository.svc”)
var binding = resolver.ResolveBinding(“wsHttpBinding_ISampleServiceBindingName”);
var endpoint = resolver.ResolveEndpoint(“wsHttpBinding_ISampleServiceEndpointName”);
var behavior = resolver.ResolveEndpointBehavior(“wsHttpBinding_ISampleServiceBehaviorName”);
SampleServiceClient proxy = new SampleServiceClient(binding, endpoint.Address, new DnsEndpointIdentity(“localhost”) );
var result = proxy.InvokeSomeOperation();
Well that’s all for now, in the next part, part two, I will go into details of How SO-Aware works with WCF 4.0 Discovery using ad hoc mode.