Overcoming issues in SvcUtil
Last week, David Pallmann posted this: http://davidpallmann.spaces.live.com/Blog/cns!E95EF9DC3FDB978E!260.entry. In it, he points out that the default values for Bindings are typically off and need to be altered. Tomas Restrepo chimed in with an 'I agree' + more opinion here: http://www.winterdom.com/weblog/2007/09/28/WCFTips.aspx
and here: http://www.winterdom.com/weblog/2007/09/28/SvcUtilGeneratedConfig.aspx
As I understood things, the main issue is that SvcUtil/VS 200x, when used in conjunction with the default settings for Bindings of all stripes, winds up giving sub-optimal settings. To fix things, people are taking the numeric settings-- buffer sizes, timeouts, parse depth, etc. -- and are setting things to maximum values just to make things work and not have to think so hard. This is not a good situation to be in and I don't like the idea that folks are starting to feel that this shortcoming means that SvcUtil and its infrastructure comprise a bad tool.
A little known/used extensibility point in WCF is the IWsdlImportExtension. This extensibility point allows one to get involved in the generation of a System.ServiceModel.Channels.Binding and influence what happens. The numeric timeouts aren't expressed in the standard set of WSDL/Policy importers, so this is a safe place to impose one's will. I created a IWsdlImportExtension that does its magic in the ImportEndpoint method. This method gives one access to the Binding that will be passed to config to create a configurable entity (see http://blogs.catalystss.com/blogs/scott_seely/archive/2007/09/28/204.aspx for how this all works).
The extension looks for an IBindingUpdater that can take the Binding that SvcUtil/VS200x created and sets defaults on that Binding. The defaults need to be visible to SvcUtil/VS 200x, so I have the defaults stored in machine.config. This isn't optimal for a production machine, but fine for most dev machines (a bigger machine.config slows down the start time of all .NET applications).
The code consists of two projects, CatSvcUtil and CatSvcUtilities. CatSvcUtil does setup of the machine.config and must be run under an Admin account. CatSvcUtilities is a strongly named assembly that contains the IWsdlImportExtension, related config, and a set of IBindingUpdaters for all standard bindings that ship in the System.ServiceModel assembly in .NET 3.5 (except MsmqIntegrationBinding). A batch file, InstallMe.bat, registers the CatSvcUtilities.dll in the GAC.
The way things work is pretty simple: the IWsdlImportExtension looks for a Binding of the same type as the other Binding and then loads a Binding from config where the name of the Binding is "default". Then, a select few of the settings are copied, typically some set that looks like this (settings missing as appropriate):
public class NetTcpBindingUpdater : IBindingUpdater
{
public void UpdateBinding(Binding binding)
{
if (binding == null)
{
throw new ArgumentNullException("binding");
}
NetTcpBinding bindingToUpdate = binding as NetTcpBinding;
if (bindingToUpdate == null)
{
throw new ArgumentException(
string.Format(CultureInfo.CurrentCulture, ExceptionResources.InvalidBindingType,
typeof (NetTcpBinding).AssemblyQualifiedName, binding.GetType().AssemblyQualifiedName),
"binding");
}
NetTcpBinding defaultBinding = new NetTcpBinding("default");
bindingToUpdate.CloseTimeout = defaultBinding.CloseTimeout;
bindingToUpdate.ListenBacklog = defaultBinding.ListenBacklog;
bindingToUpdate.MaxBufferPoolSize = defaultBinding.MaxBufferPoolSize;
bindingToUpdate.MaxBufferSize = defaultBinding.MaxBufferSize;
bindingToUpdate.MaxConnections = defaultBinding.MaxConnections;
bindingToUpdate.MaxReceivedMessageSize = defaultBinding.MaxReceivedMessageSize;
bindingToUpdate.OpenTimeout = defaultBinding.OpenTimeout;
bindingToUpdate.ReaderQuotas = defaultBinding.ReaderQuotas;
bindingToUpdate.ReceiveTimeout = defaultBinding.ReceiveTimeout;
bindingToUpdate.SendTimeout = defaultBinding.SendTimeout;
}
}
You can download and try this all out. I posted everything over at http://www.jsvap.com/ScottSeely/downloads/CatSvcUtilities.zip.
[update: you can also just grab the file from this post-- it's an attachment at the end!]
Right now, I'd love some feedback on good default settings for the various bindings. sseely@catalystss.(nospam).com. Or, leave your suggestions in comments. When I get a good set of recommendations, I'll take those suggestions and apply them in CatSvcUtil.exe (or a future setup.msi).
Again-- this changes the behavior of SvcUtil.exe and VS 2005/8 and 'fixes' those tools instead of rewriting them. I think this is what was asked for. I know it's definitely something that will come in handy for me.