Friday, 18 September 2009

Injecting service certificates into a WCF end point using Windsor’s WcfIntegration

I recently hit an issue whilst using Windsor’s WCF Integration Facility (see previous post on configuring the the facility) to create a WCF end point. Previously the WCF integration was working fine but I had to change the binding to a wsHttpBinding and use a mutual certificate to secure the message. Normally you would setup the endpoint binding to load the required certificate out of the machines certificate store, my problem was that the certificate was not  in the machines local store and needed to be loaded of disk.

The first thing to do is configure what you can in the configuration file, in my case it was setting up the wsHttpBinding.
<ws2007HttpBinding>
    <binding name="MyCustomServiceBinding">
        <security mode="Message">
            <message clientCredentialType="Certificate" negotiateServiceCredential="false" establishSecurityContext="false" />
        </security>
    </binding>
</ws2007HttpBinding>
This configures the service to use a certificate client credential type but if we were to run the service now we would get an Exception saying that no Service certificate has been specified. This is where we need to write some code and have Windsor inject it into the service host factory. To do this we need to create an end point behaviour using the IEndpointBehavior interface defined in the System.ServiceModel assembly. The method we are interested in is the AddBindingParameters method which allows us to add custom data which is added to the binding at runtime. One point to note that you should not manipulate the endpoint directly, if you do the execution behaviour is undefined.
public class MyCustomEndPointBehavior : IEndpointBehavior
{
    public void Validate(ServiceEndpoint endpoint) {}
 
    public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
    {
        var serviceCredentials = bindingParameters.Remove<ServiceCredentials>();
        serviceCredentials = serviceCredentials == null ? new ServiceCredentials() : serviceCredentials.Clone();
        serviceCredentials.ServiceCertificate.Certificate = new X509Certificate2(@"C:\FilePath\Cert.pfx","CertPassword",X509KeyStorageFlags.MachineKeySet);
        bindingParameters.Add(serviceCredentials);
    }
 
    public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) {}
 
    public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime) {}
}
What we do is look to see if there is a ServiceCredentials object in the binding parameter collection creating one if there is not and add our certificate as the ServiceCertificate. It is worth noting that this code will be run for all end points so if you have more than one you will need to use something to identify the end points you are interested such as the end points contract type.

Finally we need to wire the end point behaviour into Windsor, this is as simple as registering the type.
var myCustomEndpointBehavior = new MyCustomEndPointBehavior();
 
container.AddFacility<WcfFacility>().Register(
    Component.For<IEndpointBehavior>().Instance(myCustomEndpointBehavior),
    Component.For<IMyCustomService>().ImplementedBy<MyCustomService>());
 
DefaultServiceHostFactory.RegisterContainer(container.Kernel);
You are not limited to using the IEndpointBehavior, WCF also provides the IServiceBehavior interface which interacts at the service level (what’s in a name?). This works on the same principle but gives you access to the service host base class object but the same principles apply and again modifying the host directly will have an undefined execution behaviour.

Thursday, 17 September 2009

Using Windsor to inject dependencies into your WCF services with WCF Integration Facility

IoC is pretty cool but sometimes you can’t use it straight out of the box with say something like WCF. Well now you can thanks to Ayende Rahien. Windsor contains a WCF Integration Facility that provides a WCF ServiceHostFactory which is used to create a service host for your service and injects any dependencies registered in Windsor. This is frighteningly simple to configure as you will see.

First define your interface and implement it in your service and expose your dependencies in your class constructor as you would normally.

[ServiceContract]
public interface IMyService
{
    [OperationContract]
    void SomeAction();
}
 
public class MyService : IMyService
{
    private readonly IDependancy dependancy;
 
    public PrintJobNotificationService(IDependancy dependancy)
    {
        this.dependancy = dependancy;
    }
 
    public void SomeAction()
    {
        //Do something intelligent
    }
}

If you are exposing the service as a web service using an svc file you will need to configure it to use the Windsor ServiceHostFactory. It is important to note that the name you use for the service should be the full type name less the assembly otherwise Windsor will not be able to find it. You can use a friendly string name but you will have to name your type when you register it with Windsor.

<%@
    ServiceHost Service="MyService"
    Factory="Castle.Facilities.WcfIntegration.DefaultServiceHostFactory, Castle.Facilities.WcfIntegration"
%>

Otherwise you will need to instantiate it in code.

using(var serviceHost = new Castle.Facilities.WcfIntegration.DefaultServiceHostFactory().CreateServiceHost(typeof(WCFServices.IMyWCFService).AssemblyQualifiedName, new Uri[0]))
{
    serviceHost .Open();
}

Now you need to wire up Windsor with your service type and any dependencies as well as adding the WCF facility. You must also register your container with the Windsor’s service host factory which you can do via the static RegisterContainer on the DefaultServiceHostFactory.

container.AddFacility<WcfFacility>()
         .AddComponent<IDependancy, DependancyImplementation>()
         .Register(Component.For<IPrintJobNotificationService>().ImplementedBy<PrintJobNotificationService>());
 
DefaultServiceHostFactory.RegisterContainer(container.Kernel);

Finally you will need to configure your WCF components in the app/web.config. You can configure your endpoints and behaviours via Windsor but that is a topic for another post.

Wednesday, 9 September 2009

Generic configuration element collection

Tiered of endlessly writing your custom ConfigurationElementCollection classes and duplicating your code. Well so was I which is why I ended up abstracting out the core functionality into an abstract base class. This is a similar approach to the one Richard Adleta  used in his post on A generic ConfigurationElementCollection implementation but with some differences.

public abstract class BaseConfigurationElementCollection<TConfigurationElementType> : ConfigurationElementCollection, IList<TConfigurationElementType> where TConfigurationElementType : ConfigurationElement, IConfigurationElementCollectionElement, new()
{
    protected override ConfigurationElement CreateNewElement()
    {
        return new TConfigurationElementType();
    }
 
    protected override object GetElementKey(ConfigurationElement element)
    {
        return ((TConfigurationElementType)element).ElementKey;
    }
 
    #region Implementation of IEnumerable<TConfigurationElementType>
 
    IEnumerator<TConfigurationElement> IEnumerable<TConfigurationElement>.GetEnumerator()
    {
        foreach (TConfigurationElement type in this)
        {
            yield return type;
        }
    }
 
    #endregion
 
    #region Implementation of ICollection<TConfigurationElementType>
 
    public void Add(TConfigurationElementType configurationElement)
    {
        BaseAdd(configurationElement, true);
    }
 
    public void Clear()
    {
        BaseClear();
    }
 
    public bool Contains(TConfigurationElementType configurationElement)
    {
        return !(IndexOf(configurationElement) < 0);
    }
 
    public void CopyTo(TConfigurationElementType[] array, int arrayIndex)
    {
        base.CopyTo(array, arrayIndex);
    }
 
    public bool Remove(TConfigurationElementType configurationElement)
    {
        BaseRemove(GetElementKey(configurationElement));
 
        return true;
    }
 
    bool ICollection<TConfigurationElementType>.IsReadOnly
    {
        get { return IsReadOnly(); }
    }
 
    #endregion
 
    #region Implementation of IList<TConfigurationElementType>
 
    public int IndexOf(TConfigurationElementType configurationElement)
    {
        return BaseIndexOf(configurationElement);
    }
 
    public void Insert(int index, TConfigurationElementType configurationElement)
    {
        BaseAdd(index, configurationElement);
    }
 
    public void RemoveAt(int index)
    {
        BaseRemoveAt(index);
    }
 
    public TConfigurationElementType this[int index]
    {
        get
        {
            return (TConfigurationElementType)BaseGet(index);
        }
        set
        {
            if (BaseGet(index) != null)
            {
                BaseRemoveAt(index);
            }
            BaseAdd(index, value);
        }
    }
 
    #endregion
}

The difference between mine and Richard’s post is that my class inherits from IList<T>  and I don’t override the CollectionType property on the base class. I felt this should be done at the implementation as you also need to define the collection type in the ConfigurationCollection attribute.

The one thing that I hadn’t thought of and I borrowed from Richard was to make the generic type be an implementation of an interface for getting the elements key, in my example this is the IConfigurationElementCollectionElement interface.

Now when you want to create a configuration collection you are just left with defining the ConfigurationCollection attribute and the CollectionType and ElementName methods.

[ConfigurationCollection(typeof(CustomConfigurationElement), AddItemName = CONST_ELEMENT_NAME, CollectionType = ConfigurationElementCollectionType.BasicMap)]
public class CustomConfigurationCollection : BaseConfigurationElementCollection<CustomConfigurationElement>
{
    #region Constants
    private const string CONST_ELEMENT_NAME = "Custom";
    #endregion
 
    public override ConfigurationElementCollectionType CollectionType
    {
        get
        {
            return ConfigurationElementCollectionType.BasicMap;
        }
    }
 
    protected override string ElementName
    {
        get { return CONST_ELEMENT_NAME; }
    }
}

Happy configuring.

Edit:
Thanks to BozoJoe and britman for pointing out that my initial implementation of the IEnumerable<>GetEnumerator() was broken and they were getting a StackOverflow which was because it was recursively calling itself . I have now updated the post to fix this.