I am trying to use ASP.NET MVC 3 and Ninject 2.2 to inject a logger object into a custom ActionFilterAttribute.
I am able to get this to work if I mark each controller with the custom attribute.
However I cannot get this to work if I remove the attribute decoration from the controllers and try to use a global action filter.
Here is the code:
under App_Start - NinjectMVC3.cs
using NinjectTest.Abstract;
using NinjectTest.Concrete;
[assembly: WebActivator.PreApplicationStartMethod(typeof(NinjectTest.App_Start.NinjectMVC3), "Start")]
[assembly: WebActivator.ApplicationShutdownMethodAttribute(typeof(NinjectTest.App_Start.NinjectMVC3), "Stop")]
namespace NinjectTest.App_Start
{
using Microsoft.Web.Infrastructure.DynamicModuleHelper;
using Ninject;
using Ninject.Web.Mvc;
public static class NinjectMVC3
{
private static readonly Bootstrapper bootstrapper = new Bootstrapper();
/// <summary>
/// Starts the application
/// </summary>
public static void Start()
{
DynamicModuleUtility.RegisterModule(typeof(OnePerRequestModule));
bootstrapper.Initialize(CreateKernel);
}
/// <summary>
/// Stops the application.
/// </summary>
public static void Stop()
{
bootstrapper.ShutDown();
}
/// <summary>
/// Creates the kernel that will manage your application.
/// </summary>
/// <returns>The created kernel.</returns>
private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
RegisterServices(kernel);
return kernel;
}
/// <summary>
/// Load your modules or register your services here!
/// </summary>
/// <param name="kernel">The kernel.</param>
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<ILogger>().To<Log4NetLogger>();
}
}
}
Global.asax.cs
using System.Web.Routing;
using NinjectTest.Attributes;
namespace NinjectTest
{
public class MvcApplication : HttpApplication
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new TestLoggingAttribute());
filters.Add(new HandleErrorAttribute());
}
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
}
protected void Application_Start()
{
log4net.Config.XmlConfigurator.Configure();
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}
}
}
TestLoggingAttribute.cs
using System.Web.Mvc;
using Ninject;
using NinjectTest.Abstract;
namespace NinjectTest.Attributes
{
public class TestLoggingAttribute : ActionFilterAttribute
{
[Inject]
public ILogger _logger { get; set; }
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
var controller = filterContext.RouteData.Values["controller"];
var action = filterContext.RouteData.Values["action"];
_logger.Info("controller: " + controller + " action: " + action);
base.OnActionExecuted(filterContext);
}
}
}
HomeController.cs
using System.Web.Mvc;
using NinjectTest.Attributes;
namespace NinjectTest.Controllers
{
//[TestLogging]
public class HomeController : Controller
{
public ActionResult Index()
{
ViewBag.Message = "Welcome to ASP.NET MVC!";
return View();
}
public ActionResult About()
{
return View();
}
}
}
Like I mentioned if I uncomment the [TestLogging] attribute in the controller this all works. However I want to use a global filter instead. Can someone help me out?
Global Level Filters RegisterGlobalFilters() method. The global filters will be applied to all the controller and action methods of an application. The [HandleError] filter is applied globally in the MVC application by default in every MVC application created using Visual Studio, as shown below.
The Dependency Injection (DI) Design PatternThe Dependency Resolver in ASP.NET MVC can allow you to register your dependency logic somewhere else (e.g. a container or a bag of clubs). The advantages of using Dependency Injection pattern and Inversion of Control are the following: Reduces class coupling.
You might find the following blog post useful. So in your RegisterServices
method simply:
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<ILogger>().To<Log4NetLogger>();
kernel.BindFilter<TestLoggingAttribute>(FilterScope.Global, 0);
}
and to bring the BindFilter
extension method into scope don't forget to add a proper using
directive:
using Ninject.Web.Mvc.FilterBindingSyntax;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With