Ninject with custom attribute and filter

I am implementing a custom credit check filter for a controller action. I use Ninject as my Ioc container. First, create a action filter and implement IActionFilter interface, implement the OnActionExecuted() and OnActionExecuting() methods. Within the credit checking functions, it needs a CreditService to check against the repository and database. So I have created the parameterized constructor using Ninject to inject the CreditService object.

 public class CreditCheckFilter : IActionFilter
    {
        private ICreditService _creditService { get; set; }

        public CreditCheckFilter(ICreditService myService)
        {
            _creditService = myService;
        }

        public void OnActionExecuted(ActionExecutedContext filterContext)
        {

        }

        public void OnActionExecuting(ActionExecutingContext filterContext)
        {
            var userName = filterContext.HttpContext.User.Identity.Name;
            var bal = _creditService.GetTokenBalance(WebSecurity.GetUserId(userName));
            if (bal <= 0)
            {
                RouteValueDictionary redirectTargetDictionary = new RouteValueDictionary();
                redirectTargetDictionary.Add("action", "GetTokens");
                redirectTargetDictionary.Add("controller", "Account");
                filterContext.Result = new RedirectToRouteResult(redirectTargetDictionary);
               
            }
        }
    }

Now Let’s create a CreditCheckAttribute that implements FilterAttribute, this is the attribute we put against the controller action,

    public class CreditCheckAttribute : FilterAttribute { }

Now, we need to use Ninject BindFilter() method to bind our CreditCheckFilter, when a controller action has the attribute CreditCheckAttribute. In the ninject kernel, do this,

            kernel.BindFilter(FilterScope.Action, 0).WhenActionMethodHas();

The last step is to put CreditCheckAttribute() against the controller action,

        [CreditCheckAttribute]
        public ActionResult Playlist(TestViewModel model)
        {
            return View(model);
        }

Using Ninject in MVC 3

Previously I have chatted about how to use Structured Map and Unity for Dependency Injections. Here is the link

https://kevww.wordpress.com/tag/dependency-injection/

Today I am going to discuss how to use Ninject for your DI container.

First of all, let’s add Ninject and Ninject.MVC3 to our web application using Nuget. Here is the command you can use to install them in Package Manager Console in VS2010.

PM> Install-Package Ninject

PM> Install-Package Ninject.MVC3 -Version 2.2.2.0

Then let’s get started. And modify the Global.asax to use NinjectHttpApplication instead of HttpApplication. It overrides CreateKernel to create a kernel and load all the modules.

public class MvcApplication : NinjectHttpApplication
{
   public static void RegisterGlobalFilters(GlobalFilterCollection filters)
   {
       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
           });
   }
 
   protected override IKernel CreateKernel()
   {
       var kernel = new StandardKernel();
       kernel.Load(Assembly.GetExecutingAssembly());
       return kernel;
   }
 
   protected override void OnApplicationStarted()
   {
       base.OnApplicationStarted();
 
       AreaRegistration.RegisterAllAreas();
       RegisterGlobalFilters(GlobalFilters.Filters);
       RegisterRoutes(RouteTable.Routes);
   }
}

The only thing that has to be done is to add dependencies for controller constructor and configure the Ninject bindings for its dependencies. The controller itself will be found by Ninject even without adding a binding.

public class HomeController : Controller
{
    private readonly IWelcomeMessageService welcomeMessageService;
 
    public HomeController(IWelcomeMessageService welcomeMessageService)
    {
        this.welcomeMessageService = welcomeMessageService;
    }
 
    public void Index()
    {
        ViewModel.Message = this.welcomeMessageService.TodaysWelcomeMessage;
        return View();
    }
}
 
public class WelcomeMessageServiceModule : NinjectModule
{
    public override void Load()
    {
         this.Bind().To();
    }
}

Ninject provides contextual bindings. It allows you to register more than one binding for a type. There are 3 ways.

1. add condition to the bindings.

interface ICondition {
  bool Matches(T obj);
}

Bind().To();
Bind().To().Only(When.Context.Service.Name.StartsWith("Foo"));

2. Create Attribute

public class RangeAttribute : Attribute {}

public class Swordsman {
  [Inject] public IWeapon Weapon { get; set; }
}

public class Ninja {
  [Inject] public IWeapon MeleeWeapon { get; set; }
  [Inject, Range] public IWeapon RangeWeapon { get; set; }
}

3. Create Tags

public class Ninja {
  [Inject] public IWeapon MeleeWeapon { get; set; }
  [Inject, Tag("range")] public IWeapon RangeWeapon { get; set; }
}

Bind().To();
Bind().To().Only(When.Context.Tag == "range");

Here are some references you can read more about Ninject.

http://www.planetgeek.ch/2010/11/13/official-ninject-mvc-extension-gets-support-for-mvc3/ ( This blog post shows you how to use Ninject for Attribute bindings.)

http://bradwilson.typepad.com/blog/2010/07/service-location-pt4-filters.html

http://ninject.codeplex.com/wikipage?title=User%20Guide&referringTitle=Home (Ninject Home)