Reputation: 29953
I have a specific requirement to remove all client WCF configuration (<system.serviceModel>) out of the main app.config file, and into a separate XML file. The behaviour I would like to see is similar to that available in the appSettings section using the File="" directive. In fact, I'd ideally like to be able to specify a separate file for each consumed service...
I know I can build a custom ChannelBuilder factory that reads config data from an XML file (or a series of them), but I would prefer to still have the config data "auto-discovered" by the client.
Some basic Google searches seem to suggest this is not possible, but I wanted to get the view from SO - does anyone here know something I haven't been able to find? :)
Edit ::
Tim Scott and davogones both came up with a possible suggestion, but one which relies on splitting the component sections of the system.serviceModel section out to separate files. Although this isn't quite what I'm looking for (I'd like to define each service and its associated elements discretely, one file per service), it is an option. I'll investigate and let you know what I thought.
Upvotes: 16
Views: 28760
Reputation: 81
using System;
using System.Configuration;
using System.IO;
using System.ServiceModel;
using System.ServiceModel.Configuration;
namespace ConsoleHost
{
public class CustomServiceHost : ServiceHost
{
public CustomServiceHost(string customConfigPath, Type serviceType,
params Uri[] baseAddresses)
{
CustomConfigPath = customConfigPath;
var collection = new UriSchemeKeyedCollection(baseAddresses);
InitializeDescription(serviceType, collection);
}
public string CustomConfigPath { get; private set; }
protected override void ApplyConfiguration()
{
if (string.IsNullOrEmpty(CustomConfigPath) ||
!File.Exists(CustomConfigPath))
{
base.ApplyConfiguration();
}
else
{
LoadConfigFromCustomLocation(CustomConfigPath);
}
}
void LoadConfigFromCustomLocation(string configFilename)
{
var filemap = new ExeConfigurationFileMap
{
ExeConfigFilename = configFilename
};
Configuration config = ConfigurationManager.
OpenMappedExeConfiguration(filemap, ConfigurationUserLevel.None);
var serviceModel = ServiceModelSectionGroup.GetSectionGroup(config);
bool loaded = false;
foreach (ServiceElement se in serviceModel.Services.Services)
{
if (se.Name == Description.ConfigurationName)
{
LoadConfigurationSection(se);
loaded = true;
break;
}
}
if (!loaded)
throw new ArgumentException("ServiceElement doesn't exist");
}
}
}
After this class just use it as you would normally use it to initialize the service host
myServiceHost = new CustomServiceHost(ConfigFileName, typeof(QueryTree));
myServiceHost.Open();
Upvotes: 6
Reputation: 754388
I've been longing to do the same - basically even one step further: put my WCF config in a database table (since I can change that - can't access the file system on my hosted provider to change config files :-().
Unfortunately, this seems less than simple.....
Basically, it boils down to having to write your own custom "ServiceHost" descendant which can handle the configuration as needed.
Here's an example of loading WCF configuration from a custom config location.
This might get you going? I'm still hoping I'll be able to figure out the "loading my config from a database table" some day..... just need to quiet week at work, I guess :-)
Upvotes: 2
Reputation:
System.ServiceModel.Configuration.ConfigurationChannelFactory
et al support reading the configuration from a System.Configuration.Configuration
instance. Which means you can put the <system.servicemodel ...
stuff in a dedicated file without referencing it from web/app.config. You could have multiple config files, one for each client.
SharePoint 2010 uses that excessively in its service application model, where each service proxy reads its settings from a dedicated .config which is not necessarily web.config or app.config and isn't even referenced from there.
Upvotes: 1
Reputation: 655
I found this article that may help you out. I have not tried it, but it seems fairly straightforward.
" The configSource attribute was firstly introduced in .NET framework 2.0 to support external configuration files. This attribute can be added to any configuration section to specify an external file for that section.
Unfortunately, the system.serviceModel section group does not support this attribute. If you try to add it, you will receive the following exception:
The attribute 'configSource' cannot be specified because its name starts with the reserved prefix 'config' or 'lock'
What I found out is that you can use this attribute on the different sections under system.serviceModel such as services, behaviors or bindings. "
Upvotes: 3
Reputation: 7399
You can separate out your WCF configuration using configSource. Instructions here:
Another option is to configure your WCF services programatically.
Upvotes: 17
Reputation: 15205
You can do like this:
<system.serviceModel configSource="wcf.config"/>
Just cut your service model section out and put it in a separate file. You will have to put the whole section into the separate config file; using this method you cannot have a section span multiple files AFAIK.
Upvotes: 0
Reputation: 11243
I have a tendency to programatically configure all my service settings.
My clients aren't really the type to understand XML and have asked me make configuration files more like the old INI style.
This is easy to do (reading INI file code not included):
// create the URI which is used as the service endpoint
Uri tcpBaseAddress = new Uri(
string.Format("net.tcp://{0}:{1}",
LocalIPAddress.ToString(), GeneralPortNumber));
// create the net.tcp binding for the service endpoint
NetTcpBinding ntcBinding = new NetTcpBinding();
ntcBinding.Security.Mode = SecurityMode.None;
System.ServiceModel.Channels.Binding tcpBinding = ntcBinding;
// create the service host and add the endpoint
Host = new ServiceHost(typeof(WordWarService), tcpBaseAddress);
Since we can configure the host (and client, for that matter) programatically there is nothing keeping you from supplying the settings in any manner you choose (database, xml, crazy text file, etc).
Upvotes: 5
Reputation: 6588
I have an application at work that works kind of like what you're talking about here. We have multiple WCF services across multiple projects and all of their configuration information resides in a single config file.
The solution my company chose was to read the service configuration out of the config file and then programmatically set up the bindings, behavior, etc based on the values read. The values in the config file don't conform to the config stuff you usually see in WCF services - it was designed to be easily used by a helper class to do all the configuration at run time.
All that said, I'm not a big fan of doing that at all - too much coupling going on and it's pretty messy.
It does, though, show that it's possible - it's one thing to think about in your design.
Upvotes: 0