How to use Ninject to inject services into an authorization filter? - asp.net-mvc

I am using asp.net mvc 3, ninject 2.0 and the ninject mvc 3 plugin.
I am wondering how do I get service layers into my filter(in this case an authorization filter?).
I like to do constructor inject so is this possible or do I have to property inject?
Thanks
Edit
I have this for property inject but my property is always null
[Inject]
public IAccountService AccountServiceHelper { get; set; }
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
// check if context is set
if (httpContext == null)
{
throw new ArgumentNullException("httpContext");
}
// check if user is authenticated
if (httpContext.User.Identity.IsAuthenticated == true)
{
// stuff here
return true;
}
return false;
}
/// <summary>
/// Application_Start
/// </summary>
protected void Application_Start()
{
// Hook our DI stuff when application starts
IKernel kernel = SetupDependencyInjection();
RegisterMaps.Register();
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}
public IKernel SetupDependencyInjection()
{
IKernel kernel = CreateKernel();
// Tell ASP.NET MVC 3 to use our Ninject DI Container
DependencyResolver.SetResolver(new NinjectDependencyResolver(kernel));
return kernel;
}
protected IKernel CreateKernel()
{
var modules = new INinjectModule[]
{
new NhibernateModule(),
new ServiceModule(),
new RepoModule()
};
return new StandardKernel(modules);
}
public class ServiceModule : NinjectModule
{
public override void Load()
{
Bind<IAccountService>().To<AccountService>();
}
}
Edit
I upgraded to ninject 2.2 and get finally got it work.
Edit 2
I am going to try and do the constructor way for my authorize filter but I am unsure how to pass in the Roles. I am guessing I have to do it through ninject?
Edit 3
This is what I have so far
public class MyAuthorizeAttribute : AuthorizeAttribute
{
private readonly IAccountService accountService;
public MyAuthorizeAttribute(IAccountService accountService)
{
this.accountService = accountService;
}
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
return base.AuthorizeCore(httpContext);
}
}
this.BindFilter<MyAuthorizeAttribute>(FilterScope.Controller, 0)
.WhenControllerHas<MyAuthorizeAttribute>();
[MyAuthorize]
public class MyController : BaseController
{
}
It tells me it want's a no parameter constructor. So I must be missing something.

The problem with filters is that they are attributes. And if you define a constructor of an attribute that expects some dependency you will never gonna be able to apply it to any method: because all values that you pass to attributes must be known at compile time.
So basically you have two possibilities:
Use Ninject to apply the filter globally instead of decorating your controllers/actions with it:
public interface IFoo { }
public class Foo : IFoo { }
public class MyFooFilter : AuthorizeAttribute
{
public MyFooFilter(IFoo foo)
{
}
}
and then configure the kernel:
kernel.Bind<IFoo>().To<Foo>();
kernel.BindFilter<MyFooFilter>(FilterScope.Action, 0).When(
(controllerContext, actionDescriptor) =>
string.Equals(
controllerContext.RouteData.GetRequiredString("controller"),
"home",
StringComparison.OrdinalIgnoreCase
)
);
Use property injection:
public interface IFoo { }
public class Foo : IFoo { }
public class MyFooFilter : AuthorizeAttribute
{
[Inject]
public IFoo Foo { get; set; }
}
and then configure the kernel:
kernel.Bind<IFoo>().To<Foo>();
and decorate some controller/action with your custom filter:
[MyFooFilter]
public ActionResult Index()
{
return View();
}

See this question /answer here:
Setup filter attribute for dependency injection to accept params in constructor
and here
Dependency Injection with Ninject and Filter attribute for asp.net mvc

Related

How to use Dependency Injection with a Controller

I have below code which will work without any issue
MAUserController.cs
public class MAUserController : ApiController
{
ILogService loggerService;
IMAUserService _service;
public MAUserController(ILogService loggerService, IMAUserService Service)
{
this.loggerService = loggerService;
this._service = Service;
}
}
DependencyInstaller.cs
public class DependencyInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(
Component.For<ILogService>().ImplementedBy<LogService>().LifeStyle.PerWebRequest,
Component.For<IDatabaseFactory>().ImplementedBy<DatabaseFactory>().LifeStyle.PerWebRequest,
Component.For<IUnitOfWork>().ImplementedBy<UnitOfWork>().LifeStyle.PerWebRequest,
AllTypes.FromThisAssembly().BasedOn<IHttpController>().LifestyleTransient(),
AllTypes.FromAssemblyNamed("ISOS.Health.Service").Where(type => type.Name.EndsWith("Service")).WithServiceAllInterfaces().LifestylePerWebRequest(),
AllTypes.FromAssemblyNamed("ISOS.Health.Repository").Where(type => type.Name.EndsWith("Repository")).WithServiceAllInterfaces().LifestylePerWebRequest()
);
}
}
If I am using normal Controller instead ApiController then it gives me an error
UserController.cs
public class UserController : Controller
{
ILogService loggerService;
IMAUserService _service;
public UserController(ILogService loggerService, IMAUserService Service)
{
this.loggerService = loggerService;
this._service = Service;
}
}
This will give an error:
No parameterless constructor defined for this object
I am using CastleDI Windsor for Dependency injection.
Do I need to do anything or register something?
FIRST APPROACH
Advice: Use with caution, because it may cause memory leaks for Castle Windsor.
You have to create a controller activator, which should implement the IControllerActivator interface, in order to use your DI container to create the controller instances:
public class MyWindsorControllerActivator : IControllerActivator
{
public MyWindsorControllerActivator(IWindsorContainer container)
{
_container = container;
}
private IWindsorContainer _container;
public IController Create(RequestContext requestContext, Type controllerType)
{
return _container.Resolve(controllerType) as IController;
}
}
Then, add this class to your DependencyInstaller:
public class DependencyInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(
// Current code...
Component.For<IControllerActivator>()
.ImplementedBy<MyWindsorControllerActivator>()
.DependsOn(Dependency.OnValue("container", container))
.LifestyleSingleton();
);
}
}
Also, create your own dependency resolver based on the Windsor container:
public class MyWindsorDependencyResolver : IDependencyResolver
{
public MyWindsorDependencyResolver(IWindsorContainer container)
{
_container = container;
}
private IWindsorContainer _container;
public object GetService(Type serviceType)
{
return _container.Resolve(serviceType);
}
public IEnumerable<object> GetServices(Type serviceType)
{
return _container.ResolveAll(serviceType).Cast<object>();
}
}
Then, finally, register your dependency resolver in the Application_Start method in Global.asax.cs:
DependencyResolver.SetResolver(new MyWindsorDependencyResolver(windsorContainer));
This way, when MVC requires the controller activator through it's dependency resolver, it will get ours, which will use our Windsor container to create the controllers with all it's dependencies.
In order to avoid memory leaks using IControllerActivator, the easiest solution will be to use lifestyles like per thread or per web request, rather than the default (Singleton), transient and pooled, for the registered components. Check this link for more info about how to avoid memory leaks using Castle Windsor Container.
SECOND APPROACH
However, as pointed out by #PhilDegenhardt, a much better and correct approach will be to implement a custom controller factory, in order to be able to release the controller component created by the Castle Windsor DI Container. Here you can find an example (see the section about Dependency Injection).
Taken from that example, the implementation could be:
Global.asax.cs:
public class MvcApplication : System.Web.HttpApplication
{
private WindsorContainer _windsorContainer;
protected void Application_Start()
{
var _windsorContainer = new WindsorContainer();
_windsorContainer.Install(
new DependencyInstaller(),
// Other installers...
);
ControllerBuilder.Current.SetControllerFactory(new WindsorControllerFactory(_windsorContainer.Kernel));
}
protected void Application_End()
{
if (_windsorContainer != null)
{
_windsorContainer.Dispose();
}
}
}
WindsorControllerFactory.cs:
public class WindsorControllerFactory : DefaultControllerFactory
{
private readonly IKernel _kernel;
public WindsorControllerFactory(IKernel kernel)
{
_kernel = kernel;
}
public override void ReleaseController(IController controller)
{
_kernel.ReleaseComponent(controller); // The important part: release the component
}
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
if (controllerType == null)
{
throw new HttpException(404, string.Format("The controller for path '{0}' could not be found.", requestContext.HttpContext.Request.Path));
}
return (IController)_kernel.Resolve(controllerType);
}
}
Look at the following project link https://github.com/rarous/Castle.Windsor.Web.Mvc
Add this reference via NuGet to your MVC project, it will do the registering job for you.
Do not forget to catch your errors in global.asax.cs!
Registration :
container.Register(Component.For<IControllerFactory>().ImplementedBy<WindsorControllerFactory>());
Implementation of MVC controller factory :
using System;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using Castle.MicroKernel;
namespace Installer.Mvc
{
public class WindsorControllerFactory : DefaultControllerFactory
{
private readonly IKernel _kernel;
public WindsorControllerFactory(IKernel kernel)
{
_kernel = kernel;
}
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
if (controllerType == null)
{
throw new HttpException(404, string.Format("The controller for path '{0}' could not be found.", requestContext.HttpContext.Request.Path));
}
if (_kernel.GetHandler(controllerType) != null)
{
return (IController)_kernel.Resolve(controllerType);
}
return base.GetControllerInstance(requestContext, controllerType);
}
public override void ReleaseController(IController controller)
{
_kernel.ReleaseComponent(controller);
}
}
}

MVC Repository patterns Bind Data

I am having hard time using Repository patterns, is it possible to create two repository patterns?? One for products, another for orders??
I failed to connect these repositories to databases. I know how to work with one repository, but two with IRepository where T: Entity I am getting lost. The question is whether I can create and will not volatile the rules if create ProductRepository and OrderRepository?
Repository pattern is widely used in DDD (Domain-Driven-Design) you could check it here: http://www.infoq.com/minibooks/domain-driven-design-quickly. Also check this book: http://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215
With regards to your question:
Yes you can use more than 1 repository. Look in this example I use nHibernate session:
// crud operations
public abstract class Repository<T> : IRepository<T> where T : class
{
protected readonly ISession _session;
public Repository(ISession session)
{
_session = session;
}
public T Add(T entity)
{
_session.BeginTransaction();
//_session.SaveOrUpdate(entity);
_session.Save(entity);
_session.Transaction.Commit();
return entity;
}
//...
}
public interface IRepository<T>
{
T Add(T entity);
T Update(T entity);
T SaveOrUpdate(T entity);
bool Delete(T entity);
}
Then my repository looks like this:
public class ProjectRepository : Repository<Project>, IProjectRepository
{
// Project specific operations
}
public interface IProjectRepository : IRepository<Project>
{
Project Add(Project entity);
Project Update(Project entity);
Project find_by_id(int id);
Project find_by_id_and_user(int id, int user_id);
//..
}
Then using Ninject:
Global.asax.cs
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory());
}
Then in NinjectControllerFactory I load the modules:
public class NinjectControllerFactory : DefaultControllerFactory
{
private IKernel kernel = new StandardKernel(new NhibernateModule(), new RepositoryModule(), new DomainServiceModule());
protected override IController GetControllerInstance(RequestContext context, Type controllerType)
{
//var bindings = kernel.GetBindings(typeof(IUserService));
if (controllerType == null)
return null;
return (IController)kernel.Get(controllerType);
}
}
NhibernateModule:
public class NhibernateModule : NinjectModule
{
public override void Load()
{
string connectionString =
ConfigurationManager.ConnectionStrings["sqlite_con"].ConnectionString;
var helper = new NHibernateHelper(connectionString);
Bind<ISessionFactory>().ToConstant(helper.SessionFactory).InSingletonScope();
Bind<ISession>().ToMethod(context => context.Kernel.Get<ISessionFactory>().OpenSession()).InRequestScope();
}
}
Then in RepositoryModule I use Ninject Conventions to automatically bind all repositories with their interfaces:
using Ninject.Extensions.Conventions;
public class RepositoryModule : NinjectModule
{
public override void Load()
{
IKernel ninjectKernel = this.Kernel;
ninjectKernel.Scan(kernel =>
{
kernel.FromAssemblyContaining<ProjectRepository>();
kernel.BindWithDefaultConventions();
kernel.AutoLoadModules();
kernel.InRequestScope();
});
}
}
And in the end I basically inject Repository in the controller:
public class projectscontroller : basecontroller
{
private readonly IProjectRepository _projectRepository;
public projectscontroller(IProjectRepository projectRepository)
{
_projectRepository = projectRepository;
}
[AcceptVerbs(HttpVerbs.Get)]
[Authorize]
public ActionResult my()
{
int user_id = (User as CustomPrincipal).user_id;
var projectList = _projectRepository.find_by_user_order_by_date(user_id);
var projetsModel = new ProjectListViewModel(projectList);
return View("my", projetsModel);
}
}
This way you just create new Repository and its Interface and it will be automatically injected to your controller.

Testing protected method of AccountController

I am testing Account Controller in asp.net mvc project. I tested all methods and I looked the code coverage results, I noticed the Initialize method is not coveraged.
How can I test this method?
public class AccountController : Controller
{
public IFormsAuthenticationService FormsService { get; set; }
public IMembershipService MembershipService { get; set; }
protected override void Initialize(RequestContext requestContext)
{
if (FormsService == null) { FormsService = new FormsAuthenticationService(); }
if (MembershipService == null) { MembershipService = new AccountMembershipService(); }
base.Initialize(requestContext);
}
I tried this test method but error occured.
[TestMethod]
public void Constructor_ReturnsController()
{
RequestContext requestContext = new RequestContext(new MockHttpContext(), new RouteData());
AccountController controller = new AccountController
{
FormsService = null,
MembershipService = null,
Url = new UrlHelper(requestContext),
};
IController cont = controller;
cont.Execute(requestContext);
}
Error Message:
Test method MVC3Project.Tests.Controllers.AccountControllerTests+AccountControllerTest.Constructor_ReturnsController threw exception:
System.NotImplementedException: The method or operation is not implemented.
You will need to invoke it explicitly in your unit test:
[TestMethod]
public void AccountController_Initialize_Method_Should_WireUp_Dependencies()
{
// arrange
AccountController controller = new AccountController();
// act
controller.Initialize(null);
// assert
Assert.IsNotNull(controller.FormsService);
Assert.IsNotNull(controller.MembershipService);
}
Note that using the Initialize method to setup your dependencies is bad practice. I would recommend you using dependency injection:
public class AccountController : Controller
{
public IFormsAuthenticationService FormsService { get; private set; }
public IMembershipService MembershipService { get; private set; }
public AccountController(IFormsAuthenticationService formsService, IMembershipService membershipService)
{
FormsService = formsService;
MembershipService = membershipService;
}
... actions
}
Now you could setup your favorite dependency injection framework to inject those dependencies into your controller. For example with Ninject that's pretty easy. Install the Ninject.MVC3 NuGet and then inside the generated ~/App_Start/NinjectWebCommon.cs file configure the 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<IFormsAuthenticationService>().To<FormsAuthenticationService>();
kernel.Bind<IMembershipService>().To<AccountMembershipService>();
}
and finally you could mock those dependencies into your unit test and then define expectations on them.

MVC 3 + IoC + NInject + Repositories + LINQ

I'm trying to work with NInject in my MVC 3 application, and i have one question.
Interface
public interface ITalesRepository
{
IEnumerable<Tale> GetAllTales();
}
Repository
public class TalesRepository : ITalesRepository
{
private FairyTalesMVC3DataContext _dataContext;
public TalesRepository(FairyTalesMVC3DataContext dataContext)
{
_dataContext = dataContext;
}
public IEnumerable<Tale> GetAllTales()
{
return _dataContext.Tales.OrderBy(c => c.NameAn);
}
}
Home controller
public class HomeController : Controller
{
private readonly ITalesRepository _talesRepository;
public HomeController(ITalesRepository talesRepository)
{
_talesRepository = talesRepository;
}
public ActionResult Index()
{
ViewBag.Tales = _talesRepository.GetAllTales();
return View();
}
}
So, i need to initialize my TalesRepository with DataContext, and now it is so:
private void RegisterDependencyResolver()
{
var kernel = new StandardKernel();
kernel.Bind<ITalesRepository>().To<TalesRepository>().WithConstructorArgument("dataContext", new FairyTalesMVC3DataContext(ConfigurationManager.ConnectionStrings["dbFairyTalesConnectionString"].ConnectionString));
DependencyResolver.SetResolver(new NinjectDependencyResolver(kernel));
}
So, my question, is it ok or something wrong?
First of all:
public IEnumerable<Tale> GetAllTales()
{
return _dataContext.Tales.OrderBy(c => c.NameAn);
}
I would add .ToList() to the end. Else you'll get data layer exceptions in your presentation layer which is not fine.
Next, I would recommend that you switch to ViewModels instead of using ViewBag. It's a lot easier to prevent that logic leaks into the views if you are using ViewModels. Since you can add the logic to the ViewModel and thus get the same behaviour in all views using the model.
Your application should inherit from NinjectHttpApplication. It registers dependency resolver, so you don't have to do it.
You should also override CreateKernel in application class and register your own module with bindings:
public class MvcApplication : NinjectHttpApplication
{
protected override IKernel CreateKernel()
{
return new StandardKernel(new INinjectModule[] {new MvcModule()});
}
}
public class MvcModule : NinjectModule
{
public override void Load()
{
Bind<ITalesRepository>().To<TalesRepository>();
Bind<FairyTalesMVC3DataContext>().To<FairyTalesMVC3DataContext>().InRequestScope();
}
}

Ninject And Connection Strings

I am very new to Ninject and am trying Ninject 2 with MVC and Linq. I have a SqlProductRepository class and all I want to know is what's the best way of passing the connectionstring in the constructor if I am injecting the Repository object in the controller.
public class SqlProductRepository:IProductRepository
{
private Table<Product> productsTable;
public SqlProductRepository(string connectionString)
{
productsTable = (new DataContext(connectionString)).GetTable<Product>();
}
public IQueryable<Product> Products
{
get { return productsTable; }
}
}
This is my ProductController class where I am injecting the Repository:
public class ProductsController : Controller
{
private int pageSize = 4;
public int PageSize { get { return pageSize; } set { pageSize = value; } }
IProductRepository _productsRepository;
[Inject]
public ProductsController(IProductRepository productRepository)
{
_productsRepository = productRepository;
}
public ViewResult List(int page)
{
return View(_productsRepository.Products
.Skip((page - 1) * pageSize)
.Take(pageSize)
.ToList()
);
}
}
Can somebody please guide me regarding this?
You can set it up in your binding
_kernel.Bind<IProductRepository>()
.To<SqlProductRepository>()
.WithConstructorArgument("connectionString",yourConnectionString );
You're doing:
new DataContext(connectionString)
in your code - this is the very newing and binding to classes you're trying to push out of your code by using a DI container. At the very least, consider adding an IConnectionStringSelector interface or something like that. You dont want to have 20 Bind calls for 20 repositories - you want a higher level abstraction than that.
I'd suggest the best solution is that you should be demanding either an IDataContext or an IDataContextFactory in the constructor instead and letting that worry about it.
You could supply the connection string as a constructor argument when binding the SqlProductRepository to the IProductRepository interface.
public class LinqToSqlModule : NinjectModule
{
public override void Load()
{
Bind<IProductRepository>().To<SqlProductRepository>()
.WithConstructorArgument(connectionString, "connectionstring");
}
}
I would suggest a slightly different approach. First of all, you might want to create a binding for the DataContext class in the kernel. You could do so by using a provider class to create your DataContext passing the connection string as an argument to its constructor. Then you bind the DataContext to the DataContextProvider.
public class DataContextProvider : Provider<DataContext>
{
protected override DataContext CreateInstance(IContext context)
{
string connectionString = "connectionstring";
return new DataContext(connectionString);
}
}
public class LinqToSqlModule : NinjectModule
{
public override void Load()
{
Bind<DataContext>().ToProvider<DataContextProvider>();
Bind<IProductRepository>().To<SqlProductRepository>();
}
}
Next modify the constructor of SqlProductRepository class to accept a DataContext object instead.
public class SqlProductRepository : IProductRepository
{
private readonly DataContext context;
public ProductRepository(DataContext context)
{
this.context = context;
}
public IQueryable<Product> Products
{
get { return context.GetTable<Product>(); }
}
}
By the way you don't have to decorate your constructor with the Inject attribute. Ninject will select the constructor with the most parameters by default.
Please refer below code snap:
//Bind the default connection string
public void BindDataContext()
{
ConstructorArgument parameter = new ConstructorArgument("connectionString", "[Config Value]");
Bind<DataContext>().ToSelf().InRequestScope().WithParameter(parameter);
}
//Re-Bind the connection string (in case of multi-tenant architecture)
public void ReBindDataContext(string cn)
{
ConstructorArgument parameter = new ConstructorArgument("connectionString", cn);
Rebind<DataContext>().ToSelf().InRequestScope().WithParameter(parameter);
}
For more information, please visit below link
MVC3, Ninject and Ninject.MVC3 problem

Resources