Ninject Interception not working with MVC 5

641 views Asked by At

I am trying to implement an InterceptAttribute which should intercept any method I add the attribute to. I have it working in a WebAPI solution, however, I cannot get it to work in an MVC 5 application. The code is the same in both projects. The following code is the attribute I created.

using Ninject;
using Ninject.Extensions.Interception;
using Ninject.Extensions.Interception.Attributes;
using Ninject.Extensions.Interception.Request;

namespace Questionnaire.Common.InterceptAttributes
{
    public class InterceptCacheAttribute : InterceptAttribute
    {
        public double TimeOut { get; set; }

        public override IInterceptor CreateInterceptor(IProxyRequest request)
        {
            var cacheInterceptor = request.Kernel.Get<CacheInterceptor>();
            cacheInterceptor.TimeOut = TimeOut;
            return cacheInterceptor;
        }
    }
}

The CacheInterceptor code is as follows:

using System;
using System.Text;
using Ninject;
using Ninject.Extensions.Interception;
using Ninject.Extensions.Interception.Request;

namespace Questionnaire.Common.Interceptors
{
    public class CacheInterceptor : IInterceptor
    {
        [Inject]
        public ICaching Cache { get; set; }
        public double TimeOut { get; set; }

        public void Intercept(IInvocation invocation)
        {
            var minutes = Cache.TimeOutMinutes;
            if (Math.Abs(TimeOut - default(double)) > 0)
            {
                minutes = TimeOut;
            }
            invocation.ReturnValue = Cache.Get(GenerateCacheKey(invocation.Request), minutes, delegate
            {
                invocation.Proceed();
                return invocation.ReturnValue;
            });

        }

        private static string GenerateCacheKey(IProxyRequest request)
        {
            var sb = new StringBuilder(request.Method.Name).Append(".");
            foreach (var argument in request.Arguments)
            {
                if (argument == null)
                {
                    sb.Append("null");
                }
                else if (argument is string && argument.ToString().Length < 50)
                {
                    sb.Append((string)argument);
                }
                else
                {
                    sb.Append(argument.GetHashCode());
                }
                sb.Append(".");
            }
            sb.Remove(sb.Length - 1, 1);
            return sb.ToString();

        }
    }
}

Finally I added the attribute to the following method.

using System.Configuration;
using Questionnaire.Common.InterceptAttributes;

namespace Questionnaire.Common.Utility
{
    public class ConfigurationUtilities
    {
        [InterceptCache(TimeOut = 1440)]
        public virtual string GetEnvironmentConnectionString(string name)
        {
            var connectionStringSettings = ConfigurationManager.ConnectionStrings[name + "_" + HostEnvironment];
            return connectionStringSettings != null ? connectionStringSettings.ConnectionString : null;
        }
    }
}

Code execution never enters into the InterceptCacheAttribute class. I have put debug points within that class and the CacheInterceptor class and the debug points are never hit. The method the attribute is on executes just fine, but, I want it to be intercepted and that is not happening. I have the same code in a different project. That project is a WebAPI project which works great. The methods are intercepted and everything functions as it should. Can someone explain to me why I can't get it to work in the MVC 5 application? I would greatly appreciate it.

answer to BatteryBackupUnit's question: The answer is I can't. The following is my NinjectWebCommon.cs class.

[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(Mayo.Questionnaire.App_Start.NinjectWebCommon), "Start")]
[assembly: WebActivatorEx.ApplicationShutdownMethodAttribute(typeof(Mayo.Questionnaire.App_Start.NinjectWebCommon), "Stop")]

namespace Questionnaire.App_Start
{
    using System;
    using System.Web;
    using System.Web.Http;
    using System.Linq;
    using ApplicationExtensions;
    using Microsoft.Web.Infrastructure.DynamicModuleHelper;
    using Ninject;
    using Ninject.Web.Common;

    public static class NinjectWebCommon 
    {
        private static readonly Bootstrapper bootstrapper = new Bootstrapper();

        public static void Start() 
        {
            DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
            DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
            bootstrapper.Initialize(CreateKernel);
        }

        public static void Stop()
        {
            bootstrapper.ShutDown();
        }

        private static IKernel CreateKernel()
        {
            var kernel = new StandardKernel();
            try
            {
                kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
                kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
                GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(kernel);
                RegisterServices(kernel);
                return kernel;
            }
            catch
            {
                kernel.Dispose();
                throw;
            }
        }

        private static void RegisterServices(IKernel kernel)
        {
            foreach (var module in from assembly in AppDomain.CurrentDomain.GetAssemblies()
                     select assembly.GetNinjectModules()
                     into modules
                     from module in modules
                     where !kernel.GetModules().Any(m => m.Name.Equals(module.Name))
                     select module)
            {
                kernel.Load(module);
            }
        }        
    }
}

Inside the RegisterServices method every assembly in the application is iterated over and any classes that inherit from NinjectModule are loaded. However, I can't verify that it is working because I can't debug it. I have tried, but, execution is never stopped within the class. I know that the class is being instantiated and that the modules are being loaded because I have bindings in those modules that are working, however, I can't verify it.

0

There are 0 answers