Question

Following the sample for compression by Microsoft. I have added the encoder, encoder factory, and binding element to my solution. The difference from their sample is that we do not register our endpoints via the config file (requirement), but instead use a custom Service Host Factory.

Service Host:

protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
     ServiceHost host = base.CreateServiceHost(serviceType, baseAddresses);

     if (host.Description.Endpoints.Count == 0)
     {
          host.AddDefaultEndpoints();
     }

     host.Description.Behaviors.Add(new MessagingErrorHandler());      

     return host;
}

So what I have tried is to add a custom binding to my endpoint, but to register that endpoint with the binding it looks like I have to use the AddServiceEndpoint but that will require an interface which is unknown. I know I could get all the interfaces that the serviceType implements and do a getInterfaces()[0], but that seems to be an unsafe approach to me. So is there a way to register my endpoint with the custom binding and not know the interface, or is there a maybe a better approach that I should take.

My attempt at adding custom binding:

CustomBinding compression = new CustomBinding();
compression.Elements.Add(new GZipMessageEncodingBindingElement());
foreach (var uri in baseAddresses)
{
     host.AddServiceEndpoint(serviceType, compression, uri);//service type is not the interface and is causing the issue
}
Was it helpful?

Solution

Your custom binding needs a transport binding element; currently you only have a message encoding binding element. You need to add probably a HttpTransportBindingElement to your custom binding as well:

CustomBinding compression = new CustomBinding(
    new GZipMessageEncodingBindingElement()
    new HttpTransportBindingElement());

As far as finding the interface from the service type, there's no built-in logic for that. The logic used in the WebServiceHostFactory is similar to the one shown below (this code goes 1 inheritance / implementation level deep, but you could in theory go deeper too.

    private Type GetContractType(Type serviceType) 
    { 
        if (HasServiceContract(serviceType)) 
        { 
            return serviceType; 
        } 

        Type[] possibleContractTypes = serviceType.GetInterfaces() 
            .Where(i => HasServiceContract(i)) 
            .ToArray(); 

        switch (possibleContractTypes.Length) 
        { 
            case 0: 
                throw new InvalidOperationException("Service type " + serviceType.FullName + " does not implement any interface decorated with the ServiceContractAttribute."); 
            case 1: 
                return possibleContractTypes[0]; 
            default: 
                throw new InvalidOperationException("Service type " + serviceType.FullName + " implements multiple interfaces decorated with the ServiceContractAttribute, not supported by this factory."); 
        } 
    } 

    private static bool HasServiceContract(Type type) 
    { 
        return Attribute.IsDefined(type, typeof(ServiceContractAttribute), false); 
    }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top