entity-frameworkwcfninjectwcf-extensions

WCF with IOperationInvoker using Entity and Ninject


I have a WCF Service from which I need to log the calls to its methods. For this, I used this solution to be able to track the calls and call my internal audit service, which uses Entity 5.1 and injects the services/repositories/DbContext using Ninject.

My Invoke method looks like this:

    public object Invoke(object instance, object[] inputs, out object[] outputs)
    {
        var methodParams = (instance).GetType().GetMethod(_operationName).GetParameters();
        var parameters = new Dictionary<string, object>();
        for (var index = 0; index < inputs.Length; index++)
            parameters.Add(methodParams[index].Name, inputs[index]);

        _auditService.TrackFilterParametersValues(_operation.Parent.Type.FullName, _operationName, _operation.Action, parameters);

        return _baseInvoker.Invoke(instance, inputs, out outputs);
    }

In my Ninject module I have the internal stuff registered like this:

Bind<IAuditService>().To<AuditeService>().InRequestScope();
Bind(typeof(IRepository<>)).To(typeof(Repository<>)).InRequestScope();
Bind<IUnitOfWork>().To<UnitOfWork>().InRequestScope();
Bind<DbContext>().To<MyEntities>().InRequestScope();

Problem comes up when, inside the Repository, I call the dbContext to add the new Audit object like this:

_dbContext.Set<T>().Add(entity);

It errors out claiming that the DbContext has been disposed.

What would be the correct way of registering the DbContext on a WCF Service so it gets registered for an IOperationInvoker??

I have to mention that I have all this declaration the same for the main site I'm feeding up with this backend in MVC4 and it works perfectly (no WCF there). So I'm pretty sure something is needed to be corrected for the WCF lifetime cycle, but not so sure about what.


Solution

  • I found the reason of why this was behaving so nasty: in the chain formed by the IOperationInvoker, IOperationBehavior and IServiceBehavior, I was injecting the AuditService by the constructor of the first 2 of them, but in the latest (IServiceBehavior), since I was decorating the WCF class with it and couldn't overload the constructor, I was using the DependencyResolver to obtain the AuditService with a property like this:

    public IAuditService AuditService
    {
        get { return DependencyResolver.Current.GetService<IAuditService>();
    }
    

    Then, when I started to debug, I noticed that the constructors were called when the WCF Test Client was querying the WCF for the WSDL data, but the Invoke method was never called because no web method was being invoked. So the AuditService instance (and DbContext) was all fine during the calls of the constructors, but by the time of invoking a web method and calling the Invoke method of the IOperationInvoker, the DbContext was already disposed long time ago.

    My workaround for this was to delete all the references to the AuditService from all constructors and move the property with the DependencyResolver from the ServiceBehavior to the IOperationInvoker implementation. Once I did this, the AuditService is called right when it's needed, never before, and its DbContext is never disposed.