Dependency Injection for WCF Custom Behaviors - c#

In my WCF service I have a custom message inspector for validating incoming messages as raw XML against an XML Schema. The message inspector has a few dependencies that it takes (such as a logger and the XML schema collection). My question is, can I use a Dependency Injection framework (I'm using Ninject at the moment) to instantiate these custom behaviours and automatically inject the dependencies?
I've made a simple example demonstrating the concept:
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
using Ninject.Extensions.Logging;
public class LogMessageInspector : IDispatchMessageInspector
{
private readonly ILogger log;
public LogMessageInspector(ILogger log)
{
this.log = log;
}
public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
{
LogMessage(ref request);
return null;
}
public void BeforeSendReply(ref Message reply, object correlationState)
{
LogMessage(ref reply);
}
private void LogMessage(ref Message message)
{
//... copy the message and log using this.log ...
}
}
public class LogMessageBehavior : IEndpointBehavior
{
private readonly IDispatchMessageInspector inspector;
public LogMessageBehavior(IDispatchMessageInspector inspector)
{
this.inspector = inspector;
}
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) { }
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime) { }
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
endpointDispatcher.DispatchRuntime.MessageInspectors.Add(this.inspector);
}
public void Validate(ServiceEndpoint endpoint) { }
}
How can I go about injecting an ILogger into LogMessageInspector and a LogMessageInspector into LogMessageBehavior?
Second question, is this overkill?
Edit: I can get this to work if I build my service in code because I create the behaviour using Ninject. However, when configuring the service via config, I need to add an additional class that extends BehaviorExtensionElement. This class is created by WCF and I can't seem to find a way to cause that to be created by Ninject instead. Configured in code:
static void Main(string[] args)
{
using (IKernel kernel = new StandardKernel())
{
kernel.Bind<IEchoService>().To<EchoService>();
kernel.Bind<LogMessageInspector>().ToSelf();
kernel.Bind<LogMessageBehavior>().ToSelf();
NinjectServiceHost<EchoService> host = kernel.Get<NinjectServiceHost<EchoService>>();
ServiceEndpoint endpoint = host.AddServiceEndpoint(
typeof(IEchoService),
new NetNamedPipeBinding(),
"net.pipe://localhost/EchoService"
);
endpoint.Behaviors.Add(kernel.Get<LogMessageBehavior>());
host.Open();
Console.WriteLine("Server started, press enter to exit");
Console.ReadLine();
}
}
This works fine, but I don't know how to create the behaviour when configured via my app.config:
<system.serviceModel>
<services>
<service name="Service.EchoService">
<endpoint address="net.pipe://localhost/EchoService"
binding="netNamedPipeBinding"
contract="Contracts.IEchoService"
behaviorConfiguration="LogBehaviour"
/>
</service>
</services>
<extensions>
<behaviorExtensions>
<add name="logMessages" type="Service.LogMessagesExtensionElement, Service" />
</behaviorExtensions>
</extensions>
<behaviors>
<endpointBehaviors>
<behavior name="LogBehaviour">
<logMessages />
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
public class LogMessagesExtensionElement : BehaviorExtensionElement
{
public override Type BehaviorType
{
get { return typeof(LogMessageBehavior); }
}
protected override object CreateBehavior()
{
//how do I create an instance using the IoC container here?
}
}

How can I go about injecting an ILogger into LogMessageInspector and a
LogMessageInspector into LogMessageBehavior?
The approach has been described here
UPDATE
Please correct me if I'm wrong but I guess the question boils down to how could you get an instance of Ninject kernel in BehaviorExtensionElement.CreateBehavior? The answer depends on your hosting scenario. If hosted under IIS you could add something like this to your NinjectWebCommon:
public static StandardKernel Kernel
{
get { return (StandardKernel)bootstrapper.Kernel; }
}
Since you seem to be self-hosting, you might want to go for a static instance of the kernel too. In my view, however, this is not a terribly good idea.
I'd actually vote for your own approach and configure the behavior programmatically unless BehaviorExtensionElement is necessary because you need to be able to configure the behavior through the config file.
is this overkill?
It depends, but definitely not if you're going to unit test the implementation.

Instead of validation raw XML against an XML schema, why not take a more object oriented approach? You could for instance model each operation as a single message (a DTO) and hide the actual logic behind a generic interface. So instead of having a WCF service which contains a MoveCustomer(int customerId, Address address) method, there would be a MoveCustomerCommand { CustomerId, Address } class and the actual logic would be implemented by a class that implements the ICommandHandler<MoveCustomerCommand> interface with a single Handle(TCommand) method.
This design gives the following advantages:
Every operation in the system gets its own class (SRP)
Those message/command objects will get the WCF contract
The WCF service will contain just a single service class with a single method. This leads to a WCF service that is highly maintainable.
Allows adding cross-cutting concerns by implementing decorators for the ICommandHandler<T> interface (OCP)
Allows validation to be placed on the message/command objects (using attributes for instance) and allows this validation to be added again by using decorators.
When you apply a design based around a single generic ICommandHandler<TCommand> interface, its very easy to create generic decorators that can be applied to all implementations. Some decorators might only be needed to be applied when running inside a WCF service, others (like validation) might be needed for other application types as well.
A message could be defined as follows:
public class MoveCustomerCommand
{
[Range(1, Int32.MaxValue)]
public int CustomerId { get; set; }
[Required]
[ObjectValidator]
public Address NewAddress { get; set; }
}
This message defines an operation that will move the customer with CustomerId to the supplied NewAddress. The attributes define what state is valid. With this we can simply do object based validation using .NET DataAnnotations or Enterprise Library Validation Application Block. This is much nicer than having to write XSD based XML validations which are quite unmaintainable. And this is much nicer than having to do complex WCF configurations as you are currently trying to solve. And instead of baking this validation inside the WCF service, we can simply define a decorator class that ensures every command is validated as follows:
public class ValidationCommandHandlerDecorator<TCommand>
: ICommandHandler<TCommand>
{
private ICommandHandler<TCommand> decoratedHandler;
public ValidationCommandHandlerDecorator(
ICommandHandler<TCommand> decoratedHandler)
{
this.decoratedHandler = decoratedHandler;
}
public void Handle(TCommand command)
{
// Throws a ValidationException if invalid.
Validator.Validate(command);
this.decoratedHandler.Handle(command);
}
}
This ValidationCommandHandlerDecorator<T> decorator can be used by any type of application; not only WCF. Since WCF will by default not handle any thrown ValidationException, you might define a special decorator for WCF:
public class WcfFaultsCommandHandlerDecorator<TCommand>
: ICommandHandler<TCommand>
{
private ICommandHandler<TCommand> decoratedHandler;
public WcfFaultsCommandHandlerDecorator(
ICommandHandler<TCommand> decoratedHandler)
{
this.decoratedHandler = decoratedHandler;
}
public void Handle(TCommand command)
{
try
{
this.decoratedHandler.Handle(command);
}
catch (ValidationException ex)
{
// Allows WCF to communicate the validation
// exception back to the client.
throw new FaultException<ValidationResults>(
ex.ValidationResults);
}
}
}
Without using a DI container, a new command handler could be created as follows:
ICommandHandler<MoveCustomerCommand> handler =
new WcfFaultsCommandHandlerDecorator<MoveCustomerCommand>(
new ValidationCommandHandlerDecorator<MoveCustomerCommand>(
// the real thing
new MoveCustomerCommandHandler()
)
);
handler.Handle(command);
If you want to know more about this type of design, read the following articles:
Meanwhile... on the command side of my architecture
Writing Highly Maintainable WCF Services

Try having your LogMessageBehavior also use BehaviorExtensionElement as its base class, then you should be able to do the following:
public override Type BehaviorType
{
get { return this.GetType(); }
}
protected override object CreateBehavior()
{
return this;
}

Related

Passing a unique value to all classes using Dependency Injection?

The following code shows the flow I’m currently trying to implement within a WCF service. The service on startup calls the Bootstrapper class which uses Unity to register and resolve the required types. The Gateway class contains the public method which then kicks off the main flow of processing a message (there are many more levels to the code than is shown below).
public static class Bootstrapper
{
public static IGateway InitializeGateway()
{
IUnityContainer resolver = new UnityContainer();
resolver.RegisterType<IGateway, Gateway>();
resolver.RegisterType<ITranslator, Translator>();
resolver.RegisterType<IFormatter, IFormatter>();
return resolver.Resolve<IGateway>();
}
}
public class Gateway : IGateway
{
private readonly ITranslator translator;
private readonly IFormatter formatter;
public Gateway(ITranslator translator, IFormatter formatter)
{
this.translator = translator;
this.formatter = formatter;
}
public string ProcessMessage(string requestMessage)
{
// Create a new GUID for use in main flow for logging
Guid messageGuid = Guid.NewGuid();
requestMessage = this.translator.TranslateMessage(requestMessage);
requestMessage = this.formatter.FormatMessage(requestMessage);
return requestMessage;
}
}
Now what I’m trying to achieve is take the GUID (created for each message) and pass this down within the flow of the service such that each class has a reference to it for logging purposes.
I have tried to find a way of using DI and constructor injection but don’t know if this can be done as the GUID is created on receipt of a message by the gateway (after the bootstrapper call). What I’m trying to get away from is passing the GUID into each method as a parameter.
Any suggestions?
Instead of rolling your own solution to this problem with DI, I would recommend you use the thread-static property Trace.CorrelationManager.ActivityId for this purpose.
Take a look at this article on WCF End-To-End Tracing.

Autofac WCF Integration - Resolve dependencies based on request data

How can I configure an Autofac container so it resolves the dependencies of a WCF service based on properties values of the operation-parameter (request object)?
For example, given this data contract...
[DataContract]
public class MyRequest
{
[DataMember]
public bool MyBool { get; set; }
}
this WCF service...
public class MyWcfService : IWcfService
{
private IService m_service;
public MyWcfService(IService service)
{
m_service = service;
}
public virtual MyResponse Operation(MyRequest request) { }
}
and these dependencies...
public interface IService { }
public class TypeA : IService { }
public class TypeB : IService { }
I would like the container to resolve TypeA if MyBool equals true and TypeB otherwise. Is that feature available? Should I approach the problem differently?
Constraints:
Avoiding the Autofac.Extras.Multitenant package is a plus.
Keeping the signature of the service constructor unchanged is also desired. (See my answer below)
There are a few ways to achieve this. One of the ways is to use IIndex<K,V>. It's built-in "lookup" feature that chooses between service implementations based on a key. You can find more info on Autofac's wiki page. An example code could look like:
// Register your dependency with a key, for example a bool flag
builder.RegisterType<TypeA>().Keyed<IService>(true);
builder.RegisterType<TypeB>().Keyed<IService>(false);
// Your service could look like:
public class MyWcfService
{
private readonly IIndex<bool, IService> _services;
// Inject IIndex<Key,Value> into the constructor, Autofac will handle it automatically
public MyWcfService(IIndex<bool, IService> services)
{
_services = services;
}
public virtual void Operation(MyRequest request)
{
// Get the service that you need by the key
var service = _services[request.MyBool];
}
}
Another approach is to use Metadata feature. More information on wiki page.
Option 1 - Using Autofac:
The Autofac instance provider that creates your service instance does not use or pass along the operation's message. Here's the latest implementation of the method in Autofac. Notice the message parameter is unused.
public class AutofacInstanceProvider : IInstanceProvider
{
// lots of code removed...
public object GetInstance(InstanceContext instanceContext, Message message)
{
if (instanceContext == null)
{
throw new ArgumentNullException("instanceContext");
}
var extension = new AutofacInstanceContext(_rootLifetimeScope);
instanceContext.Extensions.Add(extension);
return extension.Resolve(_serviceData);
}
}
So to get the behavior you want with existing Autofac code, you'll need to inject the dependency into your class using something other than constructor injection, which is #Alexandr Nikitin's solution. This is reasonable, but I agree with the comment "not loving it".
Option 2 - A Custom IInstanceProvider:
Writing a custom WCF IInstanceProvider is a reasonable option, but it will be a lot of code.
The good news is that the code in Autoface.Integration.WCF is a nice example and you could plug your implementation into Autofac.
The bad news is that Autofac.Integration.WCF code doesn't itself use dependency injection. For example AutofacDependencyInjectionServiceBehavior directly calls var instanceProvider = new AutofacInstanceProvider(_rootLifetimeScope, _serviceData). As a result you'll you have to implement a replacement for AutofacInstanceProvider, AutofacDependencyInjectionServiceBehavior, AutofacHostFactory, and probably more. Then you'll need to create an extension for the AutofacInstanceContext to contain the information read from the message. Its a lot of code.
If you are going to do the custom IInstanceProvider I suggest reading up on Carlos Figueira's blog:
WCF Extensibility – IInstanceProvider - for good background
WCF Extensibility – Message Inspectors - Search for the section that starts with WCF Message objects can only be “consumed once". You'll need to follow these rules when inspecting the message.

When does WCF service host destroy custom IDispatchMessageInspector?

I have created a custom implementation of the IDispatchMessageInspector interface, and my code is working 99% fine.
My problem is that I need to free some managed objects when the WCF service host is killed and/or frees an instance of my class. My objects to free implement IDisposable but they aren't being disposed. I've been through the MSDN library (more confused) and the SO archives, but haven't found anything that addresses the question "When/where does a WCF service host destroy MessageInspectors?"
Do I need to hook an event someplace? Do I need to implement something even more arcane from the ServiceModel namespace?
Can anyone give me a pointer in the right direction?
Edit 1: Clarifications
At the moment, I am running in the IDE using the automatic webserver. I am not ultimately in control of the host once in production, could be any of the valid server host choices.
The MyCore.My and MyCore.MyProperties objects are the ones I am trying to dispose of when the WCF server host is killed/bounced.
Even when I have killed the webserver processes (those things in the Taskbar) the Dispose() is never called.
Edit 2: Code snippets added.
using /* snip */
using MyCore = Acme.My;
namespace My.SOAP
{
public class MyMessageInspector : IDispatchMessageInspector
{
protected static MyCore.My _My;
protected static MyCore.MyProperties _MyProps;
protected static ConcurrentDictionary<string, MyCore.AnotherSecretThing> _anotherSecretThings = new ConcurrentDictionary<string, MyCore.AnotherSecretThing>();
protected static void InitMy()
{
if (_My != null) return;
_MyProps = new MyCore.MyProperties();
MyCore.MySqlDatabaseLogger logger = new MyCore.MySqlDatabaseLogger(_MyProps);
_My = new MyCore.My(logger);
}
public MyMessageInspector()
{
InitMy();
}
public object AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel, System.ServiceModel.InstanceContext instanceContext)
{
MyMessageHeader header = null;
try
{
// find My header
Int32 headerPosition = request.Headers.FindHeader(MyMessageHeaderKey.MyHeaderElementName, MyMessageHeaderKey.MyNamespace);
// get reader
XmlDictionaryReader reader = request.Headers.GetReaderAtHeader(headerPosition);
// get My header object
header = MyMessageHeader.ReadHeader(reader);
// add to incoming messages properties dictionary
OperationContext.Current.IncomingMessageProperties.Add(MyMessageHeaderKey.MyHeaderElementName, header);
}
catch (Exception ex)
{
// log via ExceptionHandlingBlock
}
MyCore.SecretThings SecretThings = CreateSecretThings(/* snip */);
return SecretThings.Id;
}
public void BeforeSendReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
{
MyCore.SecretThings req = _My.GetSecretThingsOnThread();
// if we didn't find the SecretThings, there is nothing to stop() and no data to put in the MessageHeaders
if (req == null) return;
MessageBuffer buffer = reply.CreateBufferedCopy(Int32.MaxValue);
reply = buffer.CreateMessage();
var MyHeader = new MyMessageHeader(/* snip */);
reply.Headers.Add(MyHeader);
req.Stop(MyCore.Status.SUCCESS);
}
protected MyCore.SecretThings CreateSecretThings(string key, Dictionary<string, string> ids)
{
/* snip */
return _My.GetSecretThings(/* snip */);
}
}
}
I've been having a look at the DispatchMessageInspector and how it is implemented.
As you probably know you register your MessageInspectors with an IEndpointBehavior (adding endpoint behaviours through configuration or code). You create an instance of your DispatchMessageInspector within the EndpointBehaviour.
public class MyBehaviour : IEndpointBehavior
{
public void AddBindingParameters(ServiceEndpoint endpoint,
System.ServiceModel.Channels.BindingParameterCollection
bindingParameters)
{
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
var inspector = new SampleMessageInspector(); //register
endpointDispatcher.DispatchRuntime.MessageInspectors.Add(inspector);
}
public void Validate(ServiceEndpoint endpoint)
{
}
}
According to http://msdn.microsoft.com/en-us/magazine/cc163302.aspx Endpoint behaviours are registered by the Service Host
These behavior collections are automatically populated during the ServiceHost and ChannelFactory construction process with any behaviors that are found in your code (via attributes) or within the configuration file (more on this shortly). You can also add behaviors to these collections manually after construction. The following example shows how to add the ConsoleMessageTracing to the host as a service behavior:
ServiceHost host = new ServiceHost(typeof(ZipCodeService));
host.Description.Behaviors.Add(new ConsoleMessageTracing());
And further dictates that the ServiceHost has a lifetime as long as the service...
ServiceHost extension objects remain in memory for the lifetime of the ServiceHost while InstanceContext and OperationContext extension objects only remain in memory for the lifetime of the service instance or operation invocation. Your custom dispatcher/proxy extensions can use these collections to store (and look up) user-defined state throughout the pipeline.
I'm assuming this is why your objects within your MessageInspectors are never being destroyed.
Some would see it as an anti-pattern but I would possibly recommend a ServiceLocator that your MessageInspectors can use to retrieve objects. You could then look at setting their lifetime as long as its parent usage?
public class SampleMessageInspector : IDispatchMessageInspector
{
public object AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, IClientChannel channel, InstanceContext instanceContext)
{
var objectToDispose = ServiceLocator.Current.GetInstance<ObjectToDispose>();
//do your work
return null;
}
public void BeforeSendReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
{
//do some other work
}
}
To follow on from what i've mentioned...
As an example this post mentions using Ninject as the IoC container and set the life time of your objects as the lifetime of the WCF service
Bind(...).To(...).InScope(() => OperationContext.Current)
Ninject WCF Garbage Collection on repositories
You could then get access to the Ninject Kernal through the ServiceLocator and the objects (_MyProperties etc...) would be disposed off

Windsor Ioc Service Overrides: There is a component already registered for the given key

I have been trying to configure Windsor to provide a different implementation for a service depending on which class is being constrcuted:
I have read this
http://docs.castleproject.org/Windsor.Registering-components-one-by-one.ashx#Supplying_the_component_for_a_dependency_to_use_Service_override_9
and asked this yesterday
Windsor Ioc container: How to register that certain constructors take different implementation of an interface
The answer to that question works correctly when I resolve the class directly, but not when it is in an object graph a few levels deep, and the class I want to override is used as a default implementation of another interface in a different registration
e.g.
I have 2 MVC controllers. One for logging and one for cardpayments. The logging one takes a logging provider which in turn takes an IService. The CardPaymentController takes a card payment provider which in turn takes an IService. The CardPaymentProvider should get a secure service and the logging provider a normal service
code is below:
Registrations:
Component.For<ILoggingProvider>().ImplementedBy<LoggingProvider>(),
Component.For<ICardPaymentProvider>().ImplementedBy<CardPaymentProvider>(),
Component.For<IService>().ImplementedBy<WebService>().Named("default"),
Component.For<IService>().ImplementedBy<SecureWebService>().Named("secure"),
Component.For<CardPaymentProvider>().ServiceOverrides(ServiceOverride.ForKey("service").Eq("secure")),
Component.For<LoggingProvider>().ServiceOverrides(ServiceOverride.ForKey("service").Eq("default"))
Class hierarchy:
public LoggingController(ILoggingProvider loggingProvider)
{
this.loggingProvider = loggingProvider;
}
public CardPaymentController(ICardPaymentProvider cardPaymentProvider)
{
this.cardPaymentProvider = cardPaymentProvider;
}
public interface IService
{
void Doit();
}
public class WebService : IService
{
public void Doit()
{
throw new NotImplementedException();
}
}
public class SecureWebService : IService
{
public void Doit()
{
throw new NotImplementedException();
}
}
public class CardPaymentProvider : ICardPaymentProvider
{
private readonly IService service;
public CardPaymentProvider(IService service)
{
this.service = service;
}
}
public interface ICardPaymentProvider
{
}
public class LoggingProvider : ILoggingProvider
{
private readonly IService service;
public LoggingProvider(IService service)
{
this.service = service;
}
}
public interface ILoggingProvider
{
}
This produces an error on start up:
"There is a component already registered for the given key Spike.CardPaymentProvider"
If I add Named("somename") to either the CardPaymentProvider registration or the ICardPaymentProvider registration, then it starts OK, but doesn't provide a secure implementation of the service to the CardPaymentProvider - just a normal version.
What am I doing wrong?
You have to define the service overrides in the same registration. Instead of:
Component.For<ICardPaymentProvider>().ImplementedBy<CardPaymentProvider>(),
Component.For<CardPaymentProvider>().ServiceOverrides(ServiceOverride.ForKey("service").Eq("secure")),
do:
Component.For<ICardPaymentProvider>()
.ImplementedBy<CardPaymentProvider>()
.ServiceOverrides(ServiceOverride.ForKey("service").Eq("secure")),

using ninject with a remoting server

I have a class Server that implements interface IServer that is accessible using .net remoting (i have no chioce on the matter JICYAW).
internally this server uses other classes to implement logic and data access.
this server class has constructor injected dependencies that it needs to do its job.
when a client calls in (per call) the remoting framework will instatiate a Server instance using a parameterless constructor and not (of course) using Ninject.
how can i get Ninject to be the one in charge for new'ing up the class ?
i have seen this similar SO question but this isnt relevant for Ninject.
thanks for your help
You can create a service facade that will be called by the client. This facade will internally call your container to resolve the real service. For instance:
public class ServiceFacade : IService
{
private readonly IService service;
// default constructor
public ServiceFacade()
{
this.service = YourContainer.Current.Resolve<IService>();
}
void IService.ServiceOperation()
{
this.service.ServiceOperation();
}
}
What might work is to intercept the calls to those objects using a proxy and forward the calls to the real object. Note that I'm not very experienced with this, so I'm not sure if this actually works, but here goes:
public class DependencyInjectionProxy : RealProxy
{
private object realInstance;
public DependencyInjectionProxy(Type classToProxy,
object realInstance) : base(classToProxy)
{
this.realInstance = realInstance;
}
public static T MakeProxy<T>(T realInstance)
{
return (T)(new DependencyInjectionProxy(typeof(T),
realInstance).GetTransparentProxy());
}
public override IMessage Invoke(IMessage msg)
{
if (msg is IMethodCallMessage)
{
var message = (IMethodCallMessage)msg;
object value = message.MethodBase.Invoke(
this.realInstance, message.Args);
Console.WriteLine(value);
return new ReturnMessage(value, null, 0, null, message);
}
return msg;
}
}
This works when you do something like this:
var container = new YourContainer();
container.RegisterSingle<IService, Service>();
IService proxy = DependencyInjectionProxy.MakeProxy<IService>(
container.Resolve<IService>());
proxy.SomeMethod();
This works great, but to be honest, I have no idea how to configure this in a way that you can intercept incoming calls this way. Somewhere you need to register your DependencyInjectionProxy, but that's where my experience with remoting stops :-)

Categories