Quartz.NET trigger does not fire, MVC4 - asp.net-mvc-4

I have a MVC4 .Net web application on 3-tier architecture with Unity dependency injection, and I want to shedule everyday a verficiation and send some mails where is the case. For this I want to use Quartz Scheduler in Application_start, because of the dependency injection windows service is not a good option.
Here is my code in application_start.
// construct a scheduler factory
ISchedulerFactory schedFact = new StdSchedulerFactory();
IScheduler sched = schedFact.GetScheduler();
sched.Start();
IJobDetail dailyUserMailJob = new JobDetailImpl("DailyUserMailJob", null, typeof(SchedulerJob));
// fire every time I open App/EveryDay
ITrigger dailyUserMailTrigger = new SimpleTriggerImpl("DailyUserMailTrigger", 1,
new TimeSpan(1, 0, 0, 0));
sched.ScheduleJob(dailyUserMailJob, dailyUserMailTrigger);
Here is my job code :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using EvaluationMvc.Bll.Contracts;
using Quartz;
using Quartz.Impl;
namespace EvaluationMvc.Utils
{
public class SchedulerJob : IJob
{
private IEvaluationBus _iEvaluationBus;
public SchedulerJob(IEvaluationBus iEvaluationBus)
{
//Dependency injection
_iEvaluationBus = iEvaluationBus;
}
public void Execute(IJobExecutionContext context)
{
_iEvaluationBus.testingArchitecture();
// Sends a test mail.
}
}
}
However my job is never executed, what could be the problem ?

Quartz.net Scheduler must be created as singleton.
You can install Unity.MVC4 NuGet Package.
It will create a Bootstrapper class which should look something like this:
public static class Bootstrapper
{
public static IUnityContainer Initialise()
{
var container = BuildUnityContainer();
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
return container;
}
private static IUnityContainer BuildUnityContainer()
{
var container = new UnityContainer();
// Register your interfaces here.
RegisterTypes(container);
return container;
}
public static void RegisterTypes(IUnityContainer container)
{
}
}
Then you have to create your own implementation of JobFactory. This article might help you and this one is worth reading:
public class UnityJobFactory: IJobFactory
{
private readonly IUnityContainer container;
static UnityJobFactory()
{
}
public UnityJobFactory(IUnityContainer container)
{
this.container = container;
}
public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
{
var jobDetail = bundle.JobDetail;
var jobType = jobDetail.JobType;
try
{
return this.container.Resolve(jobType) as IJob;
}
catch (Exception ex)
{
throw new SchedulerException(string.Format(
CultureInfo.InvariantCulture,
"Cannot instantiate class '{0}'", new object[] { jobDetail.JobType.FullName }), ex);
}
}
public void ReturnJob(IJob job)
{
// Nothing here. Unity does not maintain a handle to container created instances.
}
}
and your own implementation of StdSchedulerFactory:
public class UnitySchedulerFactory : StdSchedulerFactory
{
private readonly UnityJobFactory unityJobFactory;
public UnitySchedulerFactory(UnityJobFactory unityJobFactory)
{
this.unityJobFactory = unityJobFactory;
}
protected override IScheduler Instantiate(QuartzSchedulerResources rsrcs, QuartzScheduler qs)
{
qs.JobFactory = this.unityJobFactory;
return base.Instantiate(rsrcs, qs);
}
}
Going back to your Unity Bootstrapper you have to register your interfaces:
private static IUnityContainer BuildUnityContainer()
{
var container = new UnityContainer();
container.RegisterType<ISchedulerFactory, UnitySchedulerFactory>(new ContainerControlledLifetimeManager());
container.RegisterType<IScheduler>(new InjectionFactory(c => c.Resolve<ISchedulerFactory>().GetScheduler()));
container.RegisterType<IQuartzScheduler, QuartzScheduler>(new ContainerControlledLifetimeManager());
container.RegisterType<IEvaluationBus, EvaluationBus>();
RegisterTypes(container);
return container;
}
I've wrapped up my service scheduler in a class so that I can create it singleton:
public interface IQuartzScheduler
{
void Run();
void Stop();
}
and:
public class QuartzScheduler : IQuartzScheduler
{
private readonly ISchedulerFactory SchedulerFactory;
private readonly IScheduler Scheduler;
public QuartzScheduler(ISchedulerFactory schedulerFactory, IScheduler scheduler)
{
this.SchedulerFactory = schedulerFactory;
this.Scheduler = scheduler;
}
public void Run()
{
IJobDetail dailyUserMailJob = new JobDetailImpl("DailyUserMailJob", null, typeof(Scheduler.SchedulerJob));
// fire every time I open App/EveryDay
ITrigger dailyUserMailTrigger = new SimpleTriggerImpl("DailyUserMailTrigger", 10,
new TimeSpan(0, 0, 0, 20));
this.Scheduler.ScheduleJob(dailyUserMailJob, dailyUserMailTrigger);
this.Scheduler.Start();
}
public void Stop()
{
this.Scheduler.Shutdown(false);
}
}
As you can see in this class I'll create my jobs/trigger and start the scheduler.
now in your Application_Start (global.asax) you can "bootstrap" your Unity Container, get the service scheduler and run it.
var unityContainer = Infrastructure.Bootstrapper.Initialise();
unityContainer.Resolve<IQuartzScheduler>().Run();
You can find a working sample following this link (QuartzWithUnity).

Very useful, thanks LeftyX. I think, in Application_Start you have to create servise like this:
var unityContainer = Bootstrapper.Initialise();
QuartzScheduler jobService = (QuartzScheduler)unityContainer.Resolve(typeof(QuartzScheduler), "Jobs");
jobService.Run();

Related

RabbitMQ channel lifetime and access in ASP Net Core

I have a ASP NET Core application that will serve as a RabbitMQ producer.I have read the tutorial and guides regarding the RabbitMQ .NET client and i still do not know how to deal with the channel lifetime and concurrent access.
From what i have read i understood the following:
IConnection is threadsafe ,but is costly to create
IModel is not threadsafe but is lightweight
For the IConnection i would initialize it in the Startup and inject it as a singleton (service).
However i I do not know how to deal with IModel management.Lets say i have a couple of services that use it, is it scalable to just :
Solution 1
public void Publish(IConnection connection)
{
using(IModel model=connection.CreateChannel())
{
model.BasicPublish(...);
}
}
Solution 2
From what i have read , i understood that its not really scalable.
So another solution would be to create a separate service which would contain a loop , a ConcurrentQueue, and all services would dispatch messages here.
This service would be the sole publisher to RabbitMQ
Publisher
public class Publisher
{
private CancellationTokenSource tcs=new CancellationTokenSource();
public BlockingCollection<byte[]> messages=new BlockingCollection<byte[]>();
private IModel channel;
private readonly string ExchangeName;
private Task loopTask;
public void Run()
{
this.loopTask=Task.Run(()=>Loop(tcs.Token),tcs.Token);
}
private void Loop(Cancellation token)
{
while(true)
{
token.ThrowIfCancellationRequested();
queue.Take(out byte[]data);
channel.BasicPublish(...,body:data);
}
}
public void Publish(byte[] message)
{
this.queue.Add(message);
}
}
Usage
public class SomeDIService
{
private IConnection connection;
SomeDIService(Publisher publisher)
{
this.publisher=publisher;
}
public void DoSomething(byte[] data)
{
//do something...
this.publisher.Publish(data);
}
}
I would prefer solution 1 but i do not know the performance penalty ,while i do not like solution 2 since i wanted to just publish messages directly to RabbitMQ.Now i have to deal with this long running Task too.
Is there any other solution , am i missing something ? Is there a simpler way?
Update
I mentioned concurrent access.I meant i need a way to publish messages from multiple endpoints (services) to RabbitMQ.
Real scenario
public class Controller1:Controller
{
private SomeDIService service; //uses Publisher
[HttpGet]
public void Endpoint1()
{
this.service.DoSomething();
}
[HttpPost]
public void Endpoint2()
{
this.service.DoSomething();
}
}
public class Controller2:Controller
{
private SomeDIService service;
[HttpGet]
public void Endpoint3()
{
this.service.DoSomething();
}
[HttpPost]
public void Endpoint4()
{
this.service.DoSomething();
}
}
after searching for long time i found this solution and it works very good for me
using Microsoft.Extensions.Options;
using RabbitMQ.Client;
using System;
using System.Collections.Generic;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
namespace BSG.MessageBroker.RabbitMQ
{
public class Rabbit : IRabbit
{
private readonly EnvConfigModel EnvConfig;
private readonly string _hostname;
private readonly string _password;
private readonly string _exchangeName;
private readonly string _username;
private IConnection _connection;
private IModel _Model;
public Rabbit(IOptions<EnvConfigModel> appSettings)
{
EnvConfig = appSettings.Value;
_Logger = services;
_exchangeName = EnvConfig.Rabbit_ExchangeName;
_hostname = EnvConfig.Rabbit_Host;
_username = EnvConfig.Rabbit_Username;
_password = EnvConfig.Rabbit_Password;
CreateConnection();
_Model = _connection.CreateModel();
}
private void CreateConnection()
{
try
{
var factory = new ConnectionFactory
{
HostName = _hostname,
UserName = _username,
Password = _password,
AutomaticRecoveryEnabled = true,
TopologyRecoveryEnabled = true,
NetworkRecoveryInterval = TimeSpan.FromSeconds(3)
};
_connection = factory.CreateConnection();
}
catch (Exception ex)
{
Console.WriteLine($"Could not create connection: {ex.Message}");
}
}
private bool ConnectionExists()
{
if (_connection != null)
{
return true;
}
CreateShredderConnection();
return _connection != null;
}
public bool PushToQueue(string Message)
{
try
{
if (ConnectionExists())
{
byte[] body = Encoding.UTF8.GetBytes(JsonSerializer.Serialize(Message));
_Model.BasicPublish(exchange: _exchangeName,
routingKey: 1001,
basicProperties: null,
body: body);
}
return true;
}
catch (Exception ex)
{
return false;
}
}
}
}

Handling Azure Redis Cache exceptions

I'm using Azure Redis Cache for development and wanted to verify the way I'm handling the exceptions. According to the best practices, it's possible to face RedisConnectionExceptions and to resolve this, we have to dispose the old ConnectionMultiplexer and create a new one. If abortConnect is set to false, then the multiplexer will silently retry connecting without throwing the error. So if the exception is thrown, it will only be after some attempts to reconect and still failing. Is my understanding of this correct?
This is my connection string -
cachename.redis.cache.windows.net:6380,password=Password,ssl=True,abortConnect=False
I believe the connection exception will only occus when you try to call GetConnection() on the multiplexer. Find my Code below -
static Lazy<ConnectionMultiplexer> multiplexer = CreateMultiplexer();
public static ConnectionMultiplexer GetConnection() => multiplexer.Value;
private static Lazy<ConnectionMultiplexer> CreateMultiplexer()
{
return new Lazy<ConnectionMultiplexer>(() => ConnectionMultiplexer.Connect(connectionString));
}
private static void CloseMultiplexer(Lazy<ConnectionMultiplexer> oldMultiplexer)
{
if (oldMultiplexer != null)
{
oldMultiplexer.Value.Close();
}
}
public static void Reconnect()
{
var oldMultiplexer = multiplexer;
CloseMultiplexer(multiplexer);
multiplexer = CreateMultiplexer();
}
And I'm Consuming this below in another class -
public class RedisCacheManager
{
private static IDatabase _cache;
private TimeSpan expiry = new TimeSpan(hours: 6, minutes: 0, seconds: 0);
public RedisCacheManager()
{
try
{
_cache = RedisCacheHelper.GetConnection().GetDatabase();
}
catch(RedisConnectionException)
{
RedisCacheHelper.Reconnect();
new RedisCacheManager();
}
}
public async Task<RedisValue[]> GetFromCacheAsync(List<string> keys)
{
var cacheValues = await _cache.StringGetAsync(keys.Select(k => (RedisKey)k).ToArray());
return cacheValues;
}
public async Task SaveInCacheAsync<TValue>(Dictionary<string, TValue> kvps)
{
var tasks = new List<Task>();
foreach(var kvp in kvps)
{
tasks.Add(_cache.StringSetAsync(kvp.Key, JsonConvert.SerializeObject(kvp), expiry));
}
await Task.WhenAll(tasks);
}
}
I'm not sure id calling the constructor in the catch block is a good practice. And are there any other exceptions that I would need to handle while calling StringGetAsync and StringSetAsync?
The CacheManager can look like this:
using Newtonsoft.Json;
using StackExchange.Redis;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
public sealed class RedisCacheManager : IDisposable
{
private readonly TimeSpan _expiry;
private readonly Lazy<ConnectionMultiplexer> _lazyConnection;
private ConnectionMultiplexer Connection { get => _lazyConnection.Value; }
public RedisCacheManager(string connectionString, TimeSpan expiry)
{
_expiry = expiry;
_lazyConnection = new Lazy<ConnectionMultiplexer>(() => ConnectionMultiplexer.Connect(connectionString));
}
public async Task<RedisValue[]> GetFromCacheAsync(IEnumerable<string> keys)
{
var cacheValues = await Connection.GetDatabase()
.StringGetAsync(keys.Select(key => (RedisKey)key).ToArray()).ConfigureAwait(false);
return cacheValues;
}
public async Task SaveInCacheAsync<TValue>(Dictionary<string, TValue> kvps)
{
var tasks = kvps
.Select(kvp => Connection.GetDatabase().StringSetAsync(kvp.Key, JsonConvert.SerializeObject(kvp), _expiry))
.ToArray();
await Task.WhenAll(tasks).ConfigureAwait(false);
}
public void Dispose()
{
if (_lazyConnection.IsValueCreated)
{
_lazyConnection.Value.Dispose();
}
}
}
Using:
public readonly static RedisCacheManager RedisCacheManager = new RedisCacheManager("connection string", TimeSpan.FromHours(6));
Remarks:
it is intended that abortConnect=false (which means that the call succeeds even if a connection to the Azure Cache for Redis is not established) and from constructor shouldn't be thrown any Redis-exceptions
The object returned from GetDatabase is a cheap pass-thru object, and does not need to be stored.
GetFromCacheAsync / SaveInCacheAsync-methods can throw an exception to outside and it is OK. You can apply Retry-policy to resolve transient faults.
If you have any IoC-container then it should create RedisCacheManager with a single instance scope (for example, Autofac registration)

Domain Events Implementation Using StructureMap Error

I am trying to grasp the fundamentals of raising/handling a Domain Event in my Solution. I am using Visual Studio 2017, .Net Core 1.1, C#, StructureMap 4.5.1.
The failure in my code came to light in a Unit Test which failed when checking if my Domain Event was being raised correctly.
My Startup.cs class includes the following code:
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddSingleton(_config);
services.AddAutoMapper();
services.AddMvc()
.AddControllersAsServices();
return ConfigureIoC(services);
}
public IServiceProvider ConfigureIoC(IServiceCollection services)
{
var container = new Container();
container.Configure(config =>
{
config.Scan(scan =>
{
scan.AssemblyContainingType(typeof(Startup));
scan.Assembly("Shared");
scan.Assembly("TaskScheduling");
scan.Assembly("TaskScheduling_Tests");
scan.WithDefaultConventions();
scan.ConnectImplementationsToTypesClosing(typeof(IHandle<>));
});
//Populate the container using the service collection
config.Populate(services);
});
return container.GetInstance<IServiceProvider>();
}
Where possible I have been following Udi Dahan's approach Domain Events - Salvation
My DomainEvents class implements the following Interface:
using System;
namespace Shared.Interfaces
{
public interface IDomainEvent
{
DateTime DateTimeEventOccurred { get; }
}
}
The DomainEvents class is as follows:
using System;
using System.Collections.Generic;
using Shared.Interfaces;
using StructureMap;
namespace Shared
{
/// <summary>
/// http://udidahan.com/2009/06/14/domain-events-salvation/
/// http://msdn.microsoft.com/en-gb/magazine/ee236415.aspx#id0400046
///
/// This class registers Domain Events and makes sure they get called.
/// </summary>
public static class DomainEvents
{
[ThreadStatic]
private static List<Delegate> actions;
public static IContainer Container { get; set; }
// Registers a callback for the given domain event.
public static void Register<T>(Action<T> callback) where T : IDomainEvent
{
if (actions == null)
{
actions = new List<Delegate>();
}
actions.Add(callback);
}
// Clears callbacks passed to Register on the current thread.
public static void ClearCallbacks()
{
actions = null;
}
// Raises the given domain event.
public static void Raise<T>(T args) where T : IDomainEvent
{
foreach (var handler in Container.GetAllInstances<IHandle<T>>())
{
handler.Handle(args);
}
if (actions != null)
{
foreach (var action in actions)
{
if (action is Action<T>)
{
((Action<T>)action)(args);
}
}
}
}
}
}
I have a Task class which when updated raises a TaskUpdatedEvent. The TaskUpdatedEvent class is as follows:
using Shared.Interfaces;
using System;
namespace TaskScheduling.Model.Events
{
public class TaskUpdatedEvent : IDomainEvent
{
/// <summary>
/// When creating a TaskUpdatedEvent you have to pass in the Task object.
/// </summary>
/// <param name="task"></param>
public TaskUpdatedEvent(ScheduleAggregate.Task task)
: this()
{
TaskUpdated = task;
}
public TaskUpdatedEvent()
{
this.Id = Guid.NewGuid();
DateTimeEventOccurred = DateTime.Now; // IDomainEvent interface requirement.
}
public Guid Id { get; private set; }
public DateTime DateTimeEventOccurred { get; private set; }
public ScheduleAggregate.Task TaskUpdated { get; private set; }
}
}
and the event is raised with the following lines in my Task class:
var taskUpdatedEvent = new TaskUpdatedEvent(this);
DomainEvents.Raise(taskUpdatedEvent);
I only have one Unit Test, so far, to check if this event is being raised. The Unit Test is as follows:
using System;
using NUnit.Framework;
using Shared;
using TaskScheduling.Model.ScheduleAggregate;
using TaskScheduling.Model.Events;
namespace TaskScheduling_Tests
{
[TestFixture]
public class TaskUpdatedEventShould
{
private Task testTask;
private readonly Guid testScheduleId = Guid.NewGuid();
private const int TestLocationId = 567;
private const int TestDeviceId = 123;
private const int TestTaskTypeId = 1;
private readonly DateTime testStartTime = new DateTime(2014, 7, 1, 9, 0, 0);
private readonly DateTime testEndTime = new DateTime(2014, 7, 1, 9, 30, 0);
private readonly DateTimeRange newTaskTimeRange = new DateTimeRange(new DateTime(2014, 6, 9, 10, 0, 0), TimeSpan.FromHours(1));
private const string TestTitle = "Unit Test Title";
[SetUp]
public void SetUp()
{
DomainEvents.ClearCallbacks();
testTask = Task.Create(
testScheduleId,
TestLocationId,
TestDeviceId,
TestTaskTypeId,
testStartTime,
testEndTime,
TestTitle
);
}
[Test]
public void EntityConstructor_IsNot_Null()
{
Assert.IsNotNull(testTask);
}
[Test]
public void RaiseTaskUpdatedEvent()
{
// Arrange
Guid updatedAppointmentId = Guid.Empty;
DomainEvents.Register<TaskUpdatedEvent>(aue =>
{
// This defines happens when the event is raised/
// The 'updatedAppointmentId' is changed from being all zeros to the testTask's id value.
updatedAppointmentId = testTask.Id;
});
// Act
testTask.UpdateTime(newTaskTimeRange);
// Assert
Assert.AreEqual(testTask.Id, updatedAppointmentId);
}
}
}
The failure appears to occur in the DomainEvent class when the Raise method is called. Debugging shows that the event is raised and the arguments are set, however the Container is Null so the foreach loop cannot check for handlers.
I cannot figure out why the Container is Null but I'm sure I must be missing something obvious. Any suggestions welcome.

Injecting Dependency into Web API Controller

I want to inject unity container into WebController.
I have UnityDependencyResolver:
public class UnityDependencyResolver : IDependencyResolver
{
readonly IUnityContainer _container;
public UnityDependencyResolver(IUnityContainer container)
{
this._container = container;
}
public object GetService(Type serviceType)
{
try
{
return _container.Resolve(serviceType);
}
catch
{
return null;
}
}
public IEnumerable<object> GetServices(Type serviceType)
{
try
{
return _container.ResolveAll(serviceType);
}
catch
{
return new List<object>();
}
}
public void Dispose()
{
_container.Dispose();
}
}
Then, in my Global.asax I add the following line:
var container = new UnityContainer();
container.RegisterType<IService, Service>
(new PerThreadLifetimeManager()).RegisterType<IDALContext, DALContext>();
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
Then, If I use the following in a Web Controller:
private IService _service;
public HomeController(IService srv)
{
_service = srv;
}
It works fine.
But I want to inject it into WebAPI Controller, so if I do it the same way:
private IService _service;
public ValuesController(IService srv)
{
_service = srv;
}
It does not work, it says that constructor is not defined.
Ok, I create one more constructor:
public ValuesController(){}
And in this case it uses only this constructor and never the one where I should inject unity container.
Please advise.
Add this in your WebApiConfig:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Routes and other stuff here...
var container = IocContainer.Instance; // Or any other way to fetch your container.
config.DependencyResolver = new UnityDependencyResolver(container);
}
}
And if you want the same container you can keep it in a static variable, like so:
public static class IocContainer
{
private static readonly Lazy<IUnityContainer> Container = new Lazy<IUnityContainer>(() =>
{
var container = new UnityContainer();
return container;
});
public static IUnityContainer Instance
{
get { return Container.Value; }
}
}
More info can be found here:
http://www.asp.net/web-api/overview/advanced/dependency-injection
On a sidenote, I can also recommend the nuget-package Unity.Mvc. It adds a UnityWebActivator and support for PerRequestLifetimeManager.
https://www.nuget.org/packages/Unity.Mvc/

Ninject Interception not working with MVC 5

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.