Dynamic applying of client's configuration

Damir Dobric Posts

Next talks:

 

    

Follow me on Twitter: #ddobric



 

 

Archives

Usually by creating of the client proxy for some service, there are two general approaches: Using of configuration file or applying required information programmatically. Additionally, the configuration can be applied by using of MetaDataResolver. In this context, sometimes the using of DynamicProxyFactory can also be helpful. Following example shows how to create dynamic proxy:

DynamicProxyFactory factory = new DynamicProxyFactory(serviceWsdlUri);

        int count = 0;

foreach (ServiceEndpoint endpoint in factory.Endpoints)

{

Console.WriteLine("Service Endpoint[{0}]", count);

Console.WriteLine("\tAddress = " + endpoint.Address);

Console.WriteLine("\tContract = " + endpoint.Contract.Name);

Console.WriteLine("\tBinding = " + endpoint.Binding.Name);

}

DynamicProxy simpleCalculatorProxy = factory.CreateProxy("ISimpleCalculator");

// Call the Add service operation.

double value1 = 100.00D;

double value2 = 15.99D;

double result = (double)simpleCalculatorProxy.CallMethod("Add", value1, value2);

However, what I missed all the time is following scenario. Imagine, there is an enterprise with many services (for example 100). In such scenario in few years there will be probably ten times more clients, which utilize these services. Imagine now what happen, when some of services just have to be moved to some other machine and the transport security mechanism has to be changed (for example from HTTP to HTTPS). In this case administrator will probably have to take care about lot of clients. In big enterprises, this kind of action costs lot of many. Because of this it is pity that the current WCF implementation does not provide an out-of the box concept for such scenarios.

The idea here is to create some service (like Active Directory) which plays a role of configuration repository. That means, the client has to know (or discover) the address of that service, which retrieves the configuration data (metadata - WSDL) for specific service. So, the client sends the request to configuration service, which retrieves the WSDL document. This WSDL document is then dynamically applied by the client. As you see, in this scenario no local configuration is needed at all.

In the next few examples I will show how to do that. First example shows how to create MetadataSet from the file which contains WSDL description. This WSDL-file (wsdlFileName) could be obtained from configuration service described above.

After we have a dataset, the ServiceEndpoint should be created, which is finally used to create the factory and proxy instances. Following example shows how to create the metadata:

public static MetadataSet CreateMetadata(MetadataSet metadata)

{

    System.Web.Services.Description.ServiceDescription serviceDescription =

System.Web.Services.Description.ServiceDescription.Read(wsdlFileName);

MetadataSection metadataSection = new MetadataSection();

metadataSection.Dialect = MetadataSection.ServiceDescriptionDialect;

metadataSection.Identifier = serviceDescription.TargetNamespace;

metadataSection.Metadata = serviceDescription;

List<MetadataSection> metadataSections = new List<MetadataSection>();

metadataSections.Add(metadataSection);

MetadataSet metadatSet = new MetadataSet(metadataSections);

return metadatSet;

}

After we obtained the metadata, the ServiceEndpoint should be created:

public static ServiceEndpoint ResolveServiceEndpoint(MetadataSet metadata)

{

WsdlImporter wsdlImporter = new WsdlImporter(metadata);

ServiceEndpointCollection services = wsdlImporter.ImportAllEndpoints();

foreach (ServiceEndpoint endpoint in services)

{

// In this example we retrieve the first endpoint

return endpoint;            

}

return null;

}

In the real scenario the WSDL document could contain more than one endpoint. In that case some proprietary algorithm should choose the preferred one.

Now, we have all necessary to create the proxy of the test interface ITestService used in this example.

ServiceEndpoint svc = ResolveServiceEndpoint(MetadataSet metadata);

ChannelFactory<ITestService> channelFactory = new ChannelFactory<ITestService>(svc.Binding, svc.Address);

ITestService proxy = channelFactory.CreateChannel();

double res = proxy.Add(1,1);

As shown in these few examples, the implementation of described scenario is more or less straight on. Note that the factory has been created from the binding and address, although the ChannelFactory has a constructor which accepts ServiceEndpoint. The problem is that creation of the proxy fails if the factory is created from endpoint:

ChannelFactory<ITestService> channelFactory = new ChannelFactory<ITestService>(svc);

Last but not least, note that just to obtain the configuration from the some remote service doesn't not solve all your problems. For example, all client specific behaviors are not the part of WSDL document.


Posted Jan 07 2007, 08:24 PM by Damir Dobric
Filed under:
developers.de is a .Net Community Blog powered by daenet GmbH.