WCF Web API Self Hosting with Unity

WCF Web API Preview 4 has been out for sometime and most examples available today still use IIS, I think only handful of example I have found uses self hosting approach and they are too simplistic or forces your service to be singleton by passing instance so I decided to provide a sample similar to the one that is available for IIS but uses and IOC container.

Configuration looks like this.

1 static void Main(string[] args) 2 { 3 4 var container = new UnityContainer(); 5 container.RegisterType(typeof(PersonResource)); 6 container.RegisterType(typeof(PeopleResource)); 7 container.RegisterType( 8 typeof(IPersonRepository), typeof(PersonRespository), 9 new ContainerControlledLifetimeManager()); 10 11 var config = HttpHostConfiguration.Create() 12 .AddFormatters(new MediaTypeFormatter[] { new JpgFormatter() }) 13 .SetResourceFactory(new UnityFactory(container)) 14 .SetErrorHandler(new CustomErrorHandler()) 15 .SetOperationHandlerFactory(new OperationHandlerFactory()) 16 .AddMessageHandlers(typeof(LoggingChannel), 17 typeof(UriFormatExtensionMessageChannel)); 18 19 var serviceHost = new UnityHttpServiceHost(typeof(PersonResource),config, 20 new Uri("http://localhost:8090/person")) 21 {Container = container}; 22 serviceHost.Open(); 23 PrintEndpointDescription(serviceHost); 24 25 Console.WriteLine("Press any key to exit"); 26 Console.ReadLine(); 27 serviceHost.Close(); 28 }

The magic is done as a part of UnityHttpServiceHost class which sets up binding, behavior and hook into the unity pipeline.

1 public class UnityHttpServiceHost : HttpServiceHost 2 { 3 public UnityContainer Container { set; get; } 4 5 public HttpHostConfiguration Configuration { get; set; } 6 7 public UnityHttpServiceHost() 8 : base() 9 { 10 Container = new UnityContainer(); 11 } 12 13 public UnityHttpServiceHost(Type serviceType, IHttpHostConfigurationBuilder builder, Uri baseAddresses) 14 : base(serviceType, baseAddresses) 15 { 16 Container = new UnityContainer(); 17 ServiceType = serviceType; 18 if (builder == null) 19 this.Configure(new HttpHostConfiguration()); 20 else 21 Configure(builder.Configuration); 22 23 } 24 25 public Type ServiceType { get; set; } 26 27 public override void AddServiceEndpoint(ServiceEndpoint endpoint) 28 { 29 var httpEndpoint = (HttpEndpoint)endpoint; 30 httpEndpoint.Binding = new HttpBinding(); 31 if (Configuration != null) 32 { 33 httpEndpoint.OperationHandlerFactory = Configuration.OperationHandlerFactory; 34 httpEndpoint.MessageHandlerFactory = Configuration.MessageHandlerFactory; 35 if (this.Configuration.ErrorHandler != null) 36 { 37 var behavior = endpoint.Behaviors.Remove<HttpBehavior>(); 38 endpoint.Behaviors.Add(new HttpBehaviorWithErrorHandler(this.Configuration.ErrorHandler) 39 { 40 OperationHandlerFactory = this.Configuration.OperationHandlerFactory 41 }); 42 } 43 if (this.Configuration.InstanceFactory != null) 44 { 45 var behavior = 46 new InstanceProviderBehavior(new ResourceFactoryProvider(this.ServiceType, 47 this.Configuration.InstanceFactory)); 48 endpoint.Behaviors.Add(behavior); 49 } 50 } 51 base.AddServiceEndpoint(endpoint); 52 } 53 54 private void Configure(HttpHostConfiguration configuration) 55 { 56 this.Configuration = configuration; 57 this.OperationHandlerFactory = configuration.OperationHandlerFactory; 58 this.MessageHandlerFactory = configuration.MessageHandlerFactory; 59 AddDefaultEndpoints(); 60 } 61 62 protected override void OnOpening() 63 { 64 new UnityServiceBehavior(Container).AddToHost(this); 65 base.OnOpening(); 66 } 67 68 }

UnityServiceBehavior looks like following. It uses UnityInstanceProvider which implements IInstanceProvider interface to manage the lifetime of resources.

1 public class UnityServiceBehavior : IServiceBehavior 2 { 3 public UnityInstanceProvider InstanceProvider 4 { 5 get; set; 6 } 7 8 private ServiceHost serviceHost = null; 9 10 public UnityServiceBehavior() 11 { 12 InstanceProvider = new UnityInstanceProvider(); 13 } 14 public UnityServiceBehavior(UnityContainer unity) 15 { 16 InstanceProvider = new UnityInstanceProvider {Container = unity}; 17 } 18 19 public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters) 20 { 21 //throw new NotImplementedException(); 22 } 23 24 public void ApplyDispatchBehavior(ServiceDescription serviceDescription,ServiceHostBase serviceHostBase) 25 { 26 foreach (ChannelDispatcherBase cdb 27 in serviceHostBase.ChannelDispatchers) 28 { 29 var cd= cdb as ChannelDispatcher; 30 if (cd != null) 31 { 32 foreach (EndpointDispatcher ed 33 in cd.Endpoints) 34 { 35 InstanceProvider.ServiceType= serviceDescription.ServiceType; 36 ed.DispatchRuntime.InstanceProvider = InstanceProvider; 37 38 } 39 } 40 } 41 }

Complete Sample can be downloaded from here

Advertisements