Ninject - Creating a Custom NinjectWebServiceHost - c#

I have a couple web services in my WCF project that require a custom ServiceAuthorizationManager to be able to authenticate OAuth calls. To do this, I created a custom WebServiceHostFactory. I am in the process of wiring up Ninject and am having a difficult time getting this converted over to a NinjectWebServiceHostFactory. Here is my code:
public class MyServiceHostFactory : WebServiceHostFactory
{
protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
return new MyServiceHost(serviceType, baseAddresses);
}
}
public class MyServiceHost: WebServiceHost
{
public MyServiceHost(Type serviceType, Uri[] baseAddresses)
: base(serviceType, baseAddresses)
{
Authorization.ServiceAuthorizationManager = new OAuthAuthorizationManager();
}
}
When I switch the WebServiceHost to a NinjectWebServiceHost it asks for an IServiceBehavior implementation. I have a ServiceBehavior attribute on my web service and I have a ServiceBehavior section in my web.config.
Has anyone seen this and been able to successfully implement something like this? Is there a better route to wire this up for my 2 web services? I do not want this to affect all of my web services.

We just did this the other day. We found it easier to implement a new type of NinjectWebServiceHostFactory that wired up the custom AuthorizationManager for us.
public class OAuthHostFactory : NinjectWebServiceHostFactory
{
protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
var host = base.CreateServiceHost(serviceType, baseAddresses);
host.Authorization.ServiceAuthorizationManager = new OAuthAuthorizationManager();
return host;
}
}
This gives us the flexibility to pick and choose which routes or svc's we want to implement this particular factory on.

I believe you'll have to create a custom attribute which implements the IServiceBehavior interface yourself.
You're ApplyDispatchBehavior method implementation will want to look something like this:
public void ApplyDispatchBehavior(ServiceDescription serviceDescription,
ServiceHostBase serviceHostBase)
{
Type serviceType = serviceDescription.ServiceType;
IInstanceProvider instanceProvider = new NinjectInstanceProvider(
new StandardKernel(), serviceType);
foreach(ChannelDispatcher dispatcher in serviceHostBase.ChannelDispatchers)
{
foreach (EndpointDispatcher endpointDispatcher in dispatcher.Endpoints)
{
DispatchRuntime dispatchRuntime = endpointDispatcher.DispatchRuntime;
dispatchRuntime.InstanceProvider = instanceProvider;
}
}
}
Basically, you're creating a custom IInstanceProvider interface implementation which depends on Ninject to create instances for the DispatchRuntime.
Peter De Rycke goes into it further in his blog entry "Using an IoC container to create WCF service instances" (note the code above was taken from there).
I imagine if you still want to use a NinjectWebServiceHost, you could pass an IServiceBehavior implementation much like the one Peter outlines above.

Related

Setup Ninject for WCF [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking us to recommend or find a book, tool, software library, tutorial or other off-site resource are off-topic for Stack Overflow as they tend to attract opinionated answers and spam. Instead, describe the problem and what has been done so far to solve it.
Closed 8 years ago.
Improve this question
Does anyone have a clear instruction on how to setup Ninject in WCF? been googling around but I cant see any updated guidelines on how to use Ninject in WCF.
Using NInject with WCF is the same as using any other DI container. To do this you need to use 3 WCF extensibility points: InstanceProvider, ServiceHost and ServiceHostFactory.
The custom InstanceProvider will be used to create service instances by using a constructor with parameters. The code can be seen below.
public class NInjectInstanceProvider : IInstanceProvider, IContractBehavior
{
private readonly IKernel kernel;
public NInjectInstanceProvider(IKernel kernel)
{
if (kernel == null) throw new ArgumentNullException("kernel");
this.kernel = kernel;
}
public object GetInstance(InstanceContext instanceContext, Message message)
{
//delegate to GetInstance(InstanceContext)
return GetInstance(instanceContext);
}
public object GetInstance(InstanceContext instanceContext)
{
//resolve the service instance
return kernel.Get(instanceContext.Host.Description.ServiceType);
}
public void ReleaseInstance(InstanceContext instanceContext, object instance)
{
kernel.Release(instance);
}
public void AddBindingParameters(ContractDescription contractDescription,
ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
}
public void ApplyClientBehavior(ContractDescription contractDescription,
ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
}
public void ApplyDispatchBehavior(ContractDescription contractDescription,
ServiceEndpoint endpoint, DispatchRuntime dispatchRuntime)
{
dispatchRuntime.InstanceProvider = this;
}
public void Validate(ContractDescription contractDescription, ServiceEndpoint endpoint)
{
}
}
This custom instance provider is then applied to every contract in the ServiceHost class. This is done by using a contract behavior. This is why the instance provider also implements IContractBehavior. You can see that we apply the instance provider in the ApplyDispatchBehavior method. The code below presents the ServiceHost and ServiceHostFactory implementations.
public class NInjectServiceHostFactory : ServiceHostFactory
{
private readonly IKernel kernel;
public NInjectServiceHostFactory()
{
kernel = new StandardKernel();
kernel.Bind<IDummyDependency>().To<DummyDepencency>();
//add the rest of the mappings here
}
protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
return new NInjectServiceHost(kernel, serviceType, baseAddresses);
}
}
public class NInjectServiceHost : ServiceHost
{
public NInjectServiceHost(IKernel kernel, Type serviceType, params Uri[] baseAddresses)
: base(serviceType, baseAddresses)
{
if (kernel == null) throw new ArgumentNullException("kernel");
foreach (var cd in ImplementedContracts.Values)
{
cd.Behaviors.Add(new NInjectInstanceProvider(kernel));
}
}
}
You can see that inside the ServiceHost constructor we iterate over all implemented contracts and apply the behavior we need. In our case this is NInjectInstanceProvider.
The custom ServiceHostFactory is required in order to create the DI container and populate it with mappings. We then override the CreateServiceHost method in order to provide our custom ServiceHost implementation.
The setup is complete at this point. All you need to do is create a WCF service that has a dependency on IDummyDependency. Also, don't forget to set the Factory attribute in the svc file like below (right click on svc file, then "View Markup"):
<%# ServiceHost Language="C#" Debug="true" Service="Service.DummyService" Factory="Service.NInjectServiceHostFactory" %>
Hope this helps. Also, I think NInject offers some implementations for this out of the box in NInject.Extensions.Wcf.dll.

How to pass dependencies to a WCF restful service

I am new to Rest services. I did fair bit of research on this topic but still not clearly understood. Hope someone clear this to me. Thanks in advance.
My client is going to execute a method on my service class through an url. All I understood is client going to call
localhost/service/get/customers
In my rest service I have dependencies like a IRepository so that I can go to database and fetch the records. If I go with constructor injection when would client call this constructor?
It looks like I need to use a service locator to fetch IRepository inside the method which I need it.
Doesn't this violate OOP principle? Is testing easy without DI?
Can anyone please clarify this.
For any service how do we expect client to know what is IRepository is what methods it does have?
Is isn't it for internal implementation purpose Do we need t expose to the client? Why should he bother about it? Can't I provide just Uri Which method to call (localhost/service/Products) and job done.
I will appreciate if you provide any live example.
Thanks a lot.
No, it will not violate OOP priciple, if you will resolve for dependency inside a method. But there is no need for that, you can use constructor Dependency Injection within WCF using Instance Provider and ServiceHostFactory, there is also good example in this question.
If you are self-hosting the service, it will be even more simpler because it requires implementing only IInstanceProvider and ServiceHost. Assuming that you have Service service with constructor taking an IDependency parameter:
public class CustomInstanceProvider : IInstanceProvider, IContractBehavior
{
private readonly IDependency dependency;
public CustomInstanceProvider(IDependency dependency)
{
this.dependency = dependency;
}
public object GetInstance(InstanceContext instanceContext)
{
// Here you are injecting dependency by constructor
return new Service(dependency);
}
public object GetInstance(InstanceContext instanceContext, Message message)
{
return this.GetInstance(instanceContext);
}
public void ReleaseInstance(InstanceContext instanceContext, object instance)
{
}
public void Validate(ContractDescription contractDescription, ServiceEndpoint endpoint)
{
}
public void ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, DispatchRuntime dispatchRuntime)
{
dispatchRuntime.InstanceProvider = this;
}
public void ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
}
public void AddBindingParameters(ContractDescription contractDescription, ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
}
}
public class CustomServiceHost : ServiceHost
{
public CustomServiceHost(IDependency dependency, Type serviceType, params Uri[] baseAddresses)
: base(serviceType, baseAddresses)
{
foreach (var cd in this.ImplementedContracts.Values)
{
cd.Behaviors.Add(new CustomInstanceProvider(dependency));
}
}
}
Then when creating service, use CustomServiceHost:
var serviceHost = new CustomServiceHost(dependency, typeof(Service), uris);

Using Castle windsor to resolve WCF service usingfactorymethod

I'm trying to see if this is possible. I want to resolve the WCF service class from castle windsor via a factory class. The WCF service is hosted in IIS and so far I've only been getting a 404 when I try to call the service when using the factory. Here is my registration code:
container.AddFacility<WcfFacility>();
container.Register(Component.For<IServiceFactory>()
.ImplementedBy<ServiceFactory>()
.LifestyleSingleton());
container.Register(Component.For<IFooService>()
.UsingFactoryMethod((kernel, context)
=> kernel.Resolve<IServiceFactory>()
.CreateService(context.RequestedType))
.Named("FooService")
.LifestylePerWcfOperation());
Here is my factory class:
public class ServiceFactory : IServiceFactory
{
public IFooService CreateService(Type forType)
{
IFooService createdType = null;
if (forType == typeof(IFooService))
createdType = new FooService();
return createdType;
}
}
I have tried doing a strait .ImplementedBy<FooService>() and that works fine. It's only when I want to do it via a factory that I have a problem. Is this possible, meaning I'm missing something, or is it not possible?
(I know that the code shown is pretty simple, I am only testing if its possible before fully implementing my factory code)
you don't have to create a custom ServiceHost to do this, though you're right this is harder than it should be. The article that eouw0o83hf references first talks about an IInstanceProvider. That's the key, but you can wire it up using and WCF ServiceBehavior as well instead of a customer ServiceHost. I'm not sure what your FactoryMethod has to do with this - it sounds like it's a general wire up issue... or I'm not understanding your problem. I'll show below how I do the wire up without the ServiceHost and hopefully that fixes your problem.
First create a class that implements IInstanceProvider - mine below calls out to my ObjectResolver class with wraps Windsor. I'll leave that out for brevity.
using System;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Dispatcher;
public class ObjectResolverInstanceProvider : IInstanceProvider
{
private readonly Type _serviceType;
public ObjectResolverInstanceProvider(Type serviceType)
{
_serviceType = serviceType;
}
public object GetInstance(InstanceContext instanceContext)
{
return ObjectResolver.Resolve(_serviceType);
}
public object GetInstance(InstanceContext instanceContext, Message message)
{
return ObjectResolver.Resolve(_serviceType);
}
public void ReleaseInstance(InstanceContext instanceContext, object instance)
{
ObjectResolver.Release(instance);
}
}
Then create a service behavior that assigns your instance provider to each endpoint's DispatchRuntime's InstanceProvider:
using System;
using System.Collections.ObjectModel;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
public class ConstructWithObjectResolverAttribute : Attribute, IServiceBehavior
{
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
foreach (ChannelDispatcherBase cdb in serviceHostBase.ChannelDispatchers)
{
ChannelDispatcher cd = cdb as ChannelDispatcher;
if (cd != null)
{
foreach (EndpointDispatcher ed in cd.Endpoints)
{
ed.DispatchRuntime.InstanceProvider = new ObjectResolverInstanceProvider(serviceDescription.ServiceType);
}
}
}
}
public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
{
}
public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
}
}
Next apply the service attribute to your service implementation... note you could do this in config if you wanted too, but I prefer applying it via an attribute like so:
[ConstructWithObjectResolver]
[ServiceBehavior(Namespace="YourNamespace")]
public class FooService : IFooService {}

Providing a factory instead of a Type in WCF ServiceHost

Is there any way to extend ServiceHost so that it accepts a factory?
I would like to use dynamic service proxies for some preprocessing of WCF calls without touching the service implementation.
EDIT
Now the ServiceHost creation looks like
var host = new ServiceHost(typeof(MyService));
and i would like to use something like
var factory = new ServiceProxyFactory<MyService>();
var host = new MyServiceHost(typeof(MyService), factory);
The interface i was looking for is IInstanceProvider.
public class MyServiceInstanceProvider<TService> : IInstanceProvider where TService : new()
{
public object GetInstance(InstanceContext instanceContext, System.ServiceModel.Channels.Message message)
{
return ServiceFactory.Create<TService>();
}
public object GetInstance(InstanceContext instanceContext)
{
return ServiceFactory.Create<TService>();
}
public void ReleaseInstance(InstanceContext instanceContext, object instance)
{
return;
}
}
public class MyEndpointBehavior<TService> : IEndpointBehavior where TService : new()
{
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
return;
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
return;
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
endpointDispatcher.DispatchRuntime.InstanceProvider = new MyServiceInstanceProvider<TService>();
}
public void Validate(ServiceEndpoint endpoint)
{
return;
}
}
public class MyServiceHost<TService> : ServiceHost where TService : new()
{
public MyServiceHost(params Uri[] baseAddresses)
:base(typeof(TService), baseAddresses)
{
}
public override System.Collections.ObjectModel.ReadOnlyCollection<ServiceEndpoint> AddDefaultEndpoints()
{
var endpoints = base.AddDefaultEndpoints();
foreach (var endpoint in endpoints)
{
endpoint.Behaviors.Add(new MyEndpointBehavior<TService>());
}
return endpoints;
}
public override void AddServiceEndpoint(ServiceEndpoint endpoint)
{
base.AddServiceEndpoint(endpoint);
endpoint.Behaviors.Add(new MyEndpointBehavior<TService>());
}
}
What you describe is not really possible with .NET...
You can implement a custom ServiceHost which allows you to customize the behaviour of the ServiceHost and/or the IDispatchMessageInspector which allows you inspect/modify any message inbound and outbound... IF you really wnat to implement some sort of "dynamic routing" then there is always the Routing capability of WCF...
Other options (though no 100% solution):
WCF service returning another service (service factory?)
WCF and factory design pattern
http://msdn.microsoft.com/en-us/library/aa702697.aspx
EDIT - I stand corrected:
It is not really possible to use a usual Factory BUT WCF provides the possibility to plug in an IInstanceProvider either at the Service or the Endpoint level...
For further reference see the following links
http://blogs.msdn.com/b/carlosfigueira/archive/2011/05/31/wcf-extensibility-iinstanceprovider.aspx
http://msdn.microsoft.com/library/system.servicemodel.dispatcher.iinstanceprovider.aspx
How do I pass values to the constructor on my wcf service?
http://geekswithblogs.net/13DaysaWeek/archive/2010/12/01/dependency-injection-and-wcf-services.aspx
http://www.eggheadcafe.com/tutorials/aspnet/b428fb65-08b4-45c8-97cd-47ee1a1eaf41/composing-wcf-applications.aspx

WCF: Using my "custom" ServiceHost in my app.config/web.config for my wcf service?

I have a created a simple Custom ServiceHost that inherits from ServiceHost and overrides the method InitializeRuntime.
How do i change my app.config / web.config to use the custom service host so my overriden InitializeRunTime is executes..
I see attributes in the config file like behaviorConfiguration etc but nothing obvious where i can force it to use my Custom ServiceHost
My ServiceHost is simple :-
public class UnityServiceHost : ServiceHost
{
protected override void InitializeRuntime()
{
//DO MY UNITY INJECTION HERE
//Console.WriteLine("");
base.InitializeRuntime();
}
}
Any help really appreciated.
Thanks
Oran Dennison describes how to do this using Spring.NET: http://orand.blogspot.com/2006/10/wcf-service-dependency-injection.html
In summary, you'll use WCF's "behavior injection" to supply an instance of the service created by your DI container.
1) Create custom IInstanceProvider implementation with the GetInstance method returning the service object created by your container:
public object GetInstance(InstanceContext instanceContext, Message message)
{
return _container.Resolve(_serviceType);
}
2) Implement a custom IServiceBehaviour that adds your custom IInstanceProvider to each endpoint configuration.
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
foreach (ChannelDispatcherBase cdb in serviceHostBase.ChannelDispatchers)
{
ChannelDispatcher cd = cdb as ChannelDispatcher;
if (cd != null)
{
foreach (EndpointDispatcher ed in cd.Endpoints)
{
ed.DispatchRuntime.InstanceProvider =
new YourCustomInstanceProvider(serviceDescription.ServiceType);
}
}
}
}
3) In your custom service host, override OnOpening and add your custom service behavior
protected override void OnOpening()
{
this.Description.Behaviors.Add(new CustomServiceBehavior());
base.OnOpening();
}
Note that you may have to pass down your UnityContainer instance through to the IInstanceProvider so that it can do the resolving.
You need to create a custom ServiceHostFactory and use that to create your UnityServiceHost. You specify the ServiceHostFactory to use in the SVC file. See the MSDN docs for the SVC syntax.
If you're hosting the service yourself (as opposed to using IIS or WAS), you should simply create a UnityServiceHost instead of a regular ServiceHost.
If you are using IIS or WAS, write a ServiceHostFactory

Categories