We're Hiring!
Take the next step in your career and work on diverse technology projects with cross-functional teams.
LEARN MORE
Mountain West Farm Bureau Insurance
office workers empowered by business technology solutions
BLOG
11
19
2012

Injecting a dependency into an action filter using ninject

Last updated:
8.4.2021

One of the most powerful features of using Inversion of Control/Dependency Injection is the ability to have highly testable code. When your dependencies are interfaces instead of concrete classes, it makes it very easy for a unit test to mock that dependency:

public class ProductsController : Controller
{
    protected readonly IProductService productService;

    public ProductsController(IProductService productService)
    {
        this.productService = productService;
    }

    [HttpPost]
    public ActionResult GetProducts()
    {
        return Json(productService.GetAllProducts());
    }
}

The above example shows an MVC controller that takes a single dependency: IProductService. There is a single action method that is using the service to get a list of products, which is being returned via JSON. Since the dependency is defined as an interface, the code is very easy to test with a mocking framework.

What happens when you want to apply the same concept to an Action Filter? Action Filters are attributes that are added to your controllers and actions at compile time so you can’t pass a dependency through the constructor. Well, with Ninject you can.

Using NuGet, install the Ninject.MVC3 package (also works in MVC 4). This will add both the Ninject and Ninject MVC packages and add a file called NinjectWebCommon.cs to the App_Start folder in your solution. This is where we will set up the dependency injection for our action filters. Before we can do that we will need to create our action filter.

For this example we will create a simple filter that could be used for logging. The first thing you need to do is create a dummy attribute that you can apply to your action methods:

public enum SeverityLevel
{
    Warning,
    Information
}

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false)]
public class LogAttribute : FilterAttribute
{
    public LogLevel Level { get; set; }
    public LogAttribute(LogLevel level)
    {
        this.Level = level;
    }
}

This can be applied to your action methods as follows:

[Log(SeverityLevel.Information)]
public Actionresult Index()
{
    return View();
}

This attribute by itself does nothing, but it will be used as a hook to inject a dependency into our real filter:

public class LogFilter : IActionFilter
{
    protected readonly ILogService logService;
    protected readonly LogLevel level;

    public LogFilter(ILogService logService, LogLevel level)
    {
        this.logService = logService;
        this.level = level;
    }

    public void OnActionExecuted(ActionExecutedContext filterContext)
    {
        // implement logging logic here
        this.logService.Log(...);
    }

    public void OnActionExecuting(ActionExecutingContext filterContext)
   {
        // implement logging logic here
        this.logService.Log(...);
    }
}

You can now write unit tests against the filter class and mock up your dependency using a mocking framework, but there is one more thing we need to do to wire everything that is up. Right now our filter has no direct tie to our attribute. Let’s change that by adding the following code to the NinjectWebCommon class in the RegisterServices method:

private static void RegisterServices(IKernel kernel)
{
    kernel.BindFilter(FilterScope.Action, 0)
        .WhenActionMethodHas()
        .WithConstructorArgumentFromActionAttribute("level", attr => attr.Level);
}

The BindFilter is is an extension method that exists in the Ninject.Web.Mvc.FilterBindingSyntax namespace. Once you add this line whenever Ninject creates an action method that has the LogAttribute applied to it, it will automatically apply the LogFilter and inject any dependencies that it knows how to create. That is all you need to get dependency injection working on an MVC action filter.

Recent Blog Posts

lunavi logo alternate white and yellow
3.13.2025
3
.
12
.
2025
Unlocking the Power of Azure Managed Services with Lunavi

Cloud computing has become the backbone of modern business, offering agility, scalability, and cost efficiency. But managing cloud environments while keeping costs under control and security airtight? That’s a challenge. Azure Managed Services streamline cloud operations, helping businesses optimize spending, enhance security, and future-proof applications. Lunavi provides the expertise and tools to make it happen—so you can focus on growth instead of IT headaches.

Learn more
lunavi logo alternate white and yellow
2.11.2025
2
.
7
.
2025
The Future of Test Automation: Key Trends Shaping 2025 and Beyond

Software testing has gone from a chore to a game-changer, thanks to automation. But in 2025, sticking to old methods means falling behind. Stay ahead by embracing the future of test automation—let’s explore the key trends shaping what’s next.

Learn more
lunavi logo alternate white and yellow
2.11.2025
1
.
23
.
2025
The Importance of Cross Browser Testing

Making sure users have a smooth experience across all these platforms is crucial for businesses to stay competitive. Cross-browser testing is now a key part of modern development. It helps teams find and fix problems like layout issues, broken features, or slow performance before users are affected. Let’s look at why cross-browser testing matters and explore tools that make it easier to get the job done.

Learn more