How To Create/Consume WCF Services With No Config File

Normally, there are a few steps we have to follow for creating or consuming a WCF service.
  • Server side - create a new ServiceHost for new WCF service.
  • Client side - make sure the correct client name is setup in client source.
  • Make sure - make sure that the .config files of both client/server side are set up properly.
Any spelling error could waste a couple of hours of investigation. I was really really tired of this job until I found some code on stackoverflow recently. Unfortunately, I could not find that thread again. Here I have attached my code instead.
  1. protected Dictionary<Type, object> GetBehaviors(string name)  
  2. {  
  3.     if (!_behaviorCache.ContainsKey(name))  
  4.     {  
  5.         BehaviorsSection behaviorData = ConfigurationManager.GetSection("system.serviceModel/behaviors"as BehaviorsSection;  
  6.         List<BehaviorExtensionElement> behaviors = new List<BehaviorExtensionElement>();  
  7.   
  8.         if (behaviorData.ServiceBehaviors.ContainsKey(name))  
  9.         {  
  10.             behaviorData.ServiceBehaviors[name].All(e =>  
  11.             {  
  12.                 behaviors.Add(e);  
  13.                 return true;  
  14.             });  
  15.         }  
  16.   
  17.         if (behaviorData.EndpointBehaviors.ContainsKey(name))  
  18.         {  
  19.             behaviorData.EndpointBehaviors[name].All(e =>  
  20.             {  
  21.                 behaviors.Add(e);  
  22.                 return true;  
  23.             });  
  24.         }  
  25.   
  26.         _behaviorCache.Add(name, behaviors.ToDictionary(e => e.BehaviorType, e => createBehavior(e)));  
  27.     }  
  28.   
  29.     return _behaviorCache[name];  
  30. }  
  31.   
  32. private object createBehavior(BehaviorExtensionElement element)  
  33. {  
  34.     return element.GetType().GetMethod("CreateBehavior", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic)  
  35.             .Invoke(element, new object[0] { });  
  36. }  
What is it? It creates a list of behaviors by given behavior name, so a ServiceHost could be created as below.
  1. private ServiceHost getServiceHost(Type serviceType, Type interfaceType)  
  2. {  
  3.     WebServiceAttribute attribute = interfaceType.GetCustomAttribute<WebServiceAttribute>();  
  4.   
  5.     if (attribute == null)  
  6.         throw new ArgumentException("WebService attribute is missing");  
  7.   
  8.     string serviceUrl = GetServiceUrl(attribute, "localhost");  
  9.     ServiceHost serviceHost = new ServiceHost(serviceType, new Uri(serviceUrl));  
  10.     var serviceMetadataBehavior = new ServiceMetadataBehavior();  
  11.     serviceHost.Description.Behaviors.Add(serviceMetadataBehavior);  
  12.   
  13.     // add behaviors  
  14.     Dictionary<Type, object> behaviors = GetBehaviors(attribute.BehaviorConfiguration);  
  15.     behaviors.All(e =>  
  16.     {  
  17.         serviceHost.Description.Behaviors.Remove(e.Key);  
  18.         serviceHost.Description.Behaviors.Add(e.Value as IServiceBehavior);  
  19.         return true;  
  20.     });  
  21.   
  22.     serviceHost.AddServiceEndpoint(interfaceType, GetBinding(attribute), serviceUrl);  
  23.     return serviceHost;  
  24. }  
If all the information could be fetched from the given attribute, is it enough for service creation? Yes!
  1. public class WebServiceAttribute : Attribute  
  2. {  
  3.     public string RelativePath { getset; }  
  4.     public Type BaseBinding { getset; }  
  5.     public string CustomBinding { getset; }  
  6.     public string BehaviorConfiguration { getset; }  
  7.     public bool UseCallback { getset; }  
  8.   
  9.     private static readonly string DEFAULT_BEHAVIOR = "customBehavior";  
  10.     private static readonly string DEFAULT_BINDING = "customWsHttpBinding";  
  11.   
  12.     public WebServiceAttribute()  
  13.     {  
  14.         UseCallback = false;  
  15.         BaseBinding = typeof(WSHttpBinding);  
  16.         CustomBinding = DEFAULT_BINDING;  
  17.         BehaviorConfiguration = DEFAULT_BEHAVIOR;  
  18.     }  
  19. }  
So, how do we use it? Just apply it on web interface, that's all.
  1. [ServiceContract]    
  2. [WebService(RelativePath = "/myapp/SimpleService/")]    
  3. public interface ISimpleService    
  4. {    
  5.     [OperationContract]    
  6.     void Speak(string words);    
  7. }  
So, with the help of WebServiceAttribute and the above codes, we are able to create a Service Host via .NET Reflection. Also, it is also possible to create a WCF Service client since this attribute contains all the information for ChannelFactory<> creation.
 
In the attached sample solution (by VS2015), you can find that the class WebServiceServerProber is used to find all available WCF services in a particular module and create ServiceHost for them; while the WebServiceSingleClientProber class is used in the client to create ChannelFactory.
 
We have saved hundreds of lines in .config file in our project. I hope it will help you! Let me know if you have any questions.
Next Recommended Reading Create WCF Service In Visual Studio 2017