Archive for August, 2007|Monthly archive page
How to add custom policy assertions to a WCF service without using a custom binding
Recently I have been trying to work with the ws policy standard to add information to our service WSDLs. WCF has an extension point for doing just that, you can read a really good example of this WCF extension here. One limitation of this method is that you must use a binding of type ‘custom’.
It is worth mentioning at this point there is a really confusing issue with WCF bindings in that there is a pre-defined binding called ‘customBinding’ that gives you control over all the binding elements that make up a WCF binding. This allows you to completely tailor the binding at configuration time. You can also create your own binding type (in code) and allow this to be used at configuration time (the method explained in this post).
So what is the problem with using a ‘customBinding’? – Well we also require our services to use 2 possible bindings either basicHttpBinding or WSHttpBinding. We could create a ‘customBinding’ that mimics basic (or ws respectively) with the addition of a ‘PolicyExporter’ Binding element. However without digging down into the details of these 2 bindings how do we know what settings to use for the ‘customBinding’. This would also lead to even more complicated web.config files. We could also easily break the service at configuration time by changing part of the customBinding.
So what do we do? – Create 2 new bindings in code, each of which derives from either basicHttpBinding or WsHttpBinding, as well as adding a ‘PolicyExporter’ binding element (or any other custom binding elements we want). We then create some other classes that allow this binding to be used at configuration time. It is possible to manually create these classes, but there is also a tool that creates these classes based on a binding (saving time etc).
Step 1 – Create the binding
In a class library that can be referenced from the web.config (we have a dll for all our WCF extensions). Define a class that inherits from the binding, and overrides ‘CreateBindingElements’ like so:
public class CustomBasicBinding:BasicHttpBinding
{
public CustomBasicBinding():base()
{
//you can even define standard binding settings here!
base.Security.Mode = BasicHttpSecurityMode.Transport;
base.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows;
}
public override BindingElementCollection CreateBindingElements()
{
BindingElementCollection bindingEls = base.CreateBindingElements();
//note that PolicyExporterBindingElement is a custom type defined elsewhere
bindingEls.Insert(0,new PolicyExporterBindingElement(new GetPoliciesFromConfig()));
return bindingEls;
}
}
Step 2 – Use the tool to generate the other classes
The WCF samples download includes a useful tool to create these other classes. Download the samples, locate the source for the tool (TechnologySamples\Tools\ConfigurationCodeGenerator\CS), build the .exe, copy the exe to wherever the .dll for your custom binding is, use a command line and run the tool:
ConfigurationCodeGenerator.exe /sb:CustomBasicBinding /dll:<dll filename>
Step 3 – Copy generated code
navigate to the location of the dll, there should be one file ‘CodeToAddTo<BindingName>‘ copy the contents of this file into your binding code. Copy the remaining generated files to your project location.
Step 4 – Use the new binding for your service
Modify the web.config for your service (either manually or using the WCF configuration tool). Add a ‘binding extension’, using the WCF config tool you can use a wizard to locate the dll and find the binding type (if you can’t see it in the dialog you’ve done something wrong!). Choose a name for the binding (used elsewhere in the config).
For any service endpoint that should use this binding, choose your new binding type as the binding for the service. If necessary you should also be able to create a BindingConfiguration (thanks to the generated code).
<extensions> <bindingExtensions> <add name="CustomBasic" type="Namespace.CustomBasicBindingCollectionElement, namespace, Version=1.0.0.1, Culture=neutral, PublicKeyToken='KEY'" /> </bindingExtensions> </extensions> ... ... <services> <service code cut for clarity> <endpoint binding="CustomBasicBinding" ... > </service> </services>
An idea for exposing additional data and fault contracts for a WCF service through behaviours
Although I am not working on this at the moment I’ve just stumbled across something that I thought I should capture as a potential solution for an existing problem.
The problem: We are using WCF behaviours to provide common functionality for all our WCF services. As part of these behaviours we need to throw specific fault contracts. However unless these are explicitly included in the service contract they are not exposed in the WSDL and so they are not visible to the client (proxy generator). It seems odd for all services to have to include these fault contract references when their own code does not actually use them at all.
Potential Solution: Use the ‘KnownType’ attribute in the WCF behaviour. I believe this tells WCF to include the specified type during serialization. So by putting this in the behaviour dll will the type appear in the WSDL?
Leave a Comment
Comments (1)