Centralizing and simplifying WCF configuration with SO-Aware

It's not a secret that WCF configuration management is one of the biggest challenges that companies face when adopting WCF as part of their enterprise solutions. Whether the declarative capabilities of the WCF programming model enable a great level of flexibility to WCF solutions they can also become a nightmare from the management standpoint. This shouldn't come as a big surprise, just imaging managing the security configuration of a few dozen WCF services across different environments (DEV, QA, PROD) and you will get pretty close to a headache ;)

The release of .NET Framework 4.0 introduced various improvements in the WCF configuration model by moving some of the default binding and behaviors configurations to the machine.config file. Whether this simplifies the development experience, its not a practical solution for medium to large size WCF solutions on which the default bindings are not sufficient to address the capabilities of the service.

SO-Aware introduced a very creative model to simplify the configuration of WCF service by combining a centralized configuration repository, the goodness of OData and the flexibility of the WCF extensibility model. The first important feature SO-Aware introduces is the ability to categorize bindings and behaviors as part of our centralized repository. The following figure helps to illustrate that concept.


To make things even simpler, SO-Aware launches with a number of preconfigured bindings and behaviors that model some of the most common WCF scenarios. This capability allow users to reuse the same binding and behavior configurations across different services. The process of configuring a service is as simple as selecting the preconfigured binding or behavior as illustrated in the following figure.


It is important to highlight that every single artifact of the service configuration can be accessed using an REST OData API via a HTTP GET.

After configuring the services in the SO-Aware portal we are ready to see the magic happen. SO-Aware includes a custom service host that, in a nutshell, resolves the service configuration from the SO-Aware repository and applies it to the target WCF service. This model not only drastically simplifies the configuration experience but it also enforces consistency on the bindings and behaviors applied to the different services. The following code illustrates the configuration experience using SO-Aware.

   1: <serviceRepository
   2:        url="http://<my web server>/SOAwarePortal/ServiceRepository.svc">
   3:     <services>
   4:         <service name="ref:CRMSOAPService(1.0)@dev" 
   5:                  type="Tellago.ServiceModel.Governance.Samples.CRMSOAPService, 
   6:                        Tellago.ServiceModel.Governance.Samples.SOAPServices"/>
   7:     </services>
   8: </serviceRepository>

In order for this model to work, the service must use a custom service host included in the SO-Aware bits.

   1: <%@ ServiceHost Language="C#" Debug="true" 
   2:  Service="Tellago.ServiceModel.Governance.Samples.CRMSOAPService"
   3:  Factory="Tellago.ServiceModel.Governance.Hosting.ConfigurableServiceHostFactory,
   4:           Tellago.ServiceModel.Governance.Hosting"  %>

As you can see, developers will only have to declare the main URI of the SO-Aware endpoint as well as the service version that needs to be configured. The simplicity of this model drastically contrasts with the traditional WCF experience on which the complete set of WCF configuration artifacts need to kept in the configuration file.

This model also enables architects to change or modify the service configuration using the centralized console without having to replicate the change on all the service configuration files.

On the client side, SO-Aware also provides an elegant programming model that enables applications to dynamically resolve the configuration from the main repository without the need to keeping a local configuration file. The following code illustrates that concept.

   1: ConfigurableProxyFactory<ICRMServiceChannel> factory = 
   2: new ConfigurableProxyFactory<ICRMServiceChannel>(ServiceUri,
   3:                               "CRMSOAPService(1.0)", "dev");
   4: ICRMServiceChannel service= factory.CreateProxy();
   5: var accounts= service.GetAccounts();

Similarly to the service programming model, the client application can resolve the configuration for a specific service by using the ConfigurableProxylFactory class. Additionally, the client application can resolve specific WCF artifacts such as bindings or behaviors by using the same programming model. The following code illustrates the steps needed to resolve a behavior that contains the certificate credentials needed to invoke a specific WCF service.

   1: factory.Endpoint.Behaviors.Remove<ClientCredentials>();
   2: factory.Endpoint.Behaviors.Add(resolver.ResolveEndpointBehavior
   3:                     ("ClientCredentialsBehavior").Behaviors[0]);

I hope this examples clearly illustrate how SO-Aware can drastically simplify the configuration of WCF services and client and, at the same time, enforce consistency and enable the management of configuration artifacts across the entire SOA infrastructure. SO-Aware uses this model internally to enforce other behaviors such as monitoring or testing which will be subject of future posts.

No Comments