Modifying code-only settings on webhosted services

There are some service settings which cannot be defined via config, only via code. If the service is hosted in a stand-alone application (via the ServiceHost class), this is not a problem - the host object is available, and from there one could use the object model to tweak all the service settings. When the service is hosted in IIS, however, this is not as simple - the main usage pattern to simply define the service and let IIS do all the hosting doesn't provide a hook for the ServiceHost object before the service is opened (and after that, most of the settings cannot be changed):

<% @ServiceHost Service="MyNamespace.MyService" %>

This directive will host the service MyNamespace.MyService in the default ServiceHost instance and open it when the first client connects to it. To perform some initialization on the host before it is opened, we need to use the Factory option of the directive to add some code before the host is actually opened:

<% @ServiceHost Service="MyNamespace.MyService" Factory="MyServiceHostFactory" Language="C#" debug="true" %>
public class MyServiceHostFactory : ServiceHostFactory
{
    protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
    {
        return new MyServiceHost(typeof(TestService), baseAddresses);
    }
}
public class MyServiceHost : ServiceHost
{
    public MyServiceHost(Type serviceType, params Uri[] baseAddresses)
        : base(serviceType, baseAddresses)
    {
    }
    protected override void ApplyConfiguration()
    {
        base.ApplyConfiguration();
        // Do any changes here. For example, this will set the contentTypeMapper option in one of the endpoints
        foreach (ServiceEndpoint endpoint in this.Description.Endpoints)
        {
            if (endpoint.Name == "TheEndpointThatNeedsToBeChanged")
            {
                CustomBinding newBinding = new CustomBinding(endpoint.Binding);
                WebMessageEncodingBindingElement webMEBE =
                    newBinding.Elements.Find<WebMessageEncodingBindingElement>();
                webMEBE.ContentTypeMapper = new MyWebContentTypeMapper();
                endpoint.Binding = newBinding;
            }
        }
    }
}

This was one of the solutions for the problem described in the (very long) thread at https://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2348599&SiteID=1.