I am trying to implement Dependency Injection with Autofac in an ASP.NET MVC5 Project. But I am getting the following error every time:
None of the constructors found with 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type 'MyProjectName.DAL.Repository` ........
My Autofac configuration code in App_Start folder as follows:
public static class IocConfigurator
{
public static void ConfigureDependencyInjection()
{
var builder = new ContainerBuilder();
builder.RegisterControllers(typeof(MvcApplication).Assembly);
builder.RegisterType<Repository<Student>>().As<IRepository<Student>>();
IContainer container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
}
}
In Global.asax file:
public class MvcApplication : HttpApplication
{
protected void Application_Start()
{
// Other MVC setup
IocConfigurator.ConfigureDependencyInjection();
}
}
Here is my IRepository:
public interface IRepository<TEntity> where TEntity: class
{
IQueryable<TEntity> GelAllEntities();
TEntity GetById(object id);
void InsertEntity(TEntity entity);
void UpdateEntity(TEntity entity);
void DeleteEntity(object id);
void Save();
void Dispose();
}
Here is my Repository:
public class Repository<TEntity> : IRepository<TEntity>, IDisposable where TEntity : class
{
internal SchoolContext context;
internal DbSet<TEntity> dbSet;
public Repository(SchoolContext dbContext)
{
context = dbContext;
dbSet = context.Set<TEntity>();
}
.....................
}
Here is my Student Controller:
public class StudentController : Controller
{
private readonly IRepository<Student> _studentRepository;
public StudentController()
{
}
public StudentController(IRepository<Student> studentRepository)
{
this._studentRepository = studentRepository;
}
....................
}
What's wrong in my Autofac Configuration..Any Help Please??
To inject a dependency you need to have satisfied all of the dependencies for all of the pieces down the chain.
In your case, the Repository constructor cannot be satisfied without a SchoolContext.
So in your registration add:
builder.RegisterType<SchoolContext>().InstancePerRequest();
See http://docs.autofac.org/en/latest/lifetime/instance-scope.html#instance-per-request
Related
I am trying to use RenderMvcController and SurfaceController with dependency injection but it doesn't work.
public class SupplierRenderMvcController : RenderMvcController
{
public HomeRenderMvcController(IMembershipService membershipService)
{
_membershipService = membershipService;
}
}
public class SupplierController : SurfaceController
{
public SupplierController(IMembershipService membershipService)
{
_membershipService = membershipService;
}
}
I get an error:
No parameterless constructor defined for this object.
Umbraco's controllers are registered in in Global.asax:
builder.RegisterControllers(typeof(UmbracoApplication).Assembly);
builder.RegisterApiControllers(typeof(UmbracoApplication).Assembly);
I have api controllers using IoC with no problem in other projects of the same solution.
The above controllers are in the main project of the solution though.
This is my full Global.asax of the main project:
public class MvcApplication : IApplicationEventHandler
{
public void OnApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
{
AreaRegistration.RegisterAllAreas();
BundleConfig.RegisterBundles(BundleTable.Bundles);
GlobalConfiguration.Configuration.Formatters.XmlFormatter.SupportedMediaTypes.Clear();
RegisterIoCContainer();
}
public void OnApplicationInitialized(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
{
}
public void OnApplicationStarting(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
{
}
private void RegisterIoCContainer()
{
var builder = new ContainerBuilder();
builder.RegisterControllers(Assembly.GetExecutingAssembly());
builder.RegisterAssemblyModules(Assembly.GetExecutingAssembly());
builder.RegisterModelBinders(Assembly.GetExecutingAssembly());
builder.RegisterModelBinderProvider();
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
builder.RegisterControllers(typeof(UmbracoApplication).Assembly);
builder.RegisterApiControllers(typeof(UmbracoApplication).Assembly);
builder.RegisterApiControllers(Assembly.GetExecutingAssembly‌​());
builder.RegisterModule<WebApiConfig>();
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
GlobalConfiguration.Configuration.DependencyResolver = new AutofacWebApiDependencyResolver(container);
GlobalConfiguration.Configuration.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always;
}
}
MembershipService is registered within WebApiConfig:
public class WebApiConfig : Module
{
protected override void Load(ContainerBuilder builder)
{
builder.AddMediatR(this.GetType().Assembly);
builder.RegisterType<MembershipService1>().As<IMembershipService>();
}
}
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);
}
}
}
I have WebApi project with ODataController and I'm trying to inject some dependency into MyController. I was following this blogpost by Mark Seemann.
Consider code below.
Problem is, that when is MyController creating, I got exception inside WindsorCompositionRoot Create method on this line,
var controller = (IHttpController)this.container.Resolve(controllerType);
An exception of type 'Castle.MicroKernel.ComponentNotFoundException'
occurred in Castle.Windsor.dll but was not handled in user code
Additional information: No component for supporting the service
System.Web.OData.MetadataController was found
Any idea how to fix this?
Thank you.
My controller:
public class MyController : ODataController
{
private readonly DataLayer _db;
public PrepravyController(DataLayer db)
{
_db = db;
}
}
CompositonRoot:
public class WindsorCompositionRoot : IHttpControllerActivator
{
private readonly IWindsorContainer container;
public WindsorCompositionRoot(IWindsorContainer container)
{
this.container = container;
}
public IHttpController Create(
HttpRequestMessage request,
HttpControllerDescriptor controllerDescriptor,
Type controllerType)
{
var controller =
(IHttpController)this.container.Resolve(controllerType);
request.RegisterForDispose(
new Release(
() => this.container.Release(controller)));
return controller;
}
private class Release : IDisposable
{
private readonly Action release;
public Release(Action release)
{
this.release = release;
}
public void Dispose()
{
this.release();
}
}
}
Global asax:
var container = new WindsorContainer();
container.Install(new RepositoriesInstaller());
GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpControllerActivator), new WindsorCompositionRoot(container));
GlobalConfiguration.Configure(WebApiConfig.Register);
Make sure you're registering all your controllers with the container:
public class ControllerInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(Classes.FromThisAssembly().BasedOn<IController>().LifestylePerWebRequest())
.Register(Classes.FromThisAssembly().BasedOn<ApiController>().LifestylePerWebRequest());
}
}
Windsor uses installers to encapsulate and partition registration logic. It also includes a helper called FromAssembly, so you don't need to manually instantiate all your installers:
_container = new WindsorContainer();
_container.Install(FromAssembly.This());
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.
I am trying to pass my unitofwork into my generic base repository, but when i try and call some of the methods the unitofwork isnt being passed into the base repository.
The scenario: I inject the userRepository below into my UserController all fine, its when it calls the userRepository.Save(user) it fails due to the unitofwork being null. Im not sure why though?
Im using nhibernate and structuremap. I think ive wired everything up correctly but here is some code to double check:
Here is the base repository:
public class BaseRepository<T> : IRepository<T> where T : IAggregateRoot
{
private readonly IUnitOfWork _unitOfWork;
public BaseRepository(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
public BaseRepository()
{}
public void Save(T Entity)
{
_unitOfWork.Session.Save(Entity);
}
}
A specific repository:
public class UserRepository : BaseRepository<User>, IUserRepository
{
}
This is my nhibernate structuremap configuration:
public NhibernateRegistry()
{
For<IUnitOfWork>().HybridHttpOrThreadLocalScoped().Use<UnitOfWork>();
For(typeof(IRepository<>)).Use(typeof(BaseRepository<>));
// Nhibernate Session
For<ISession>().HybridHttpOrThreadLocalScoped().Use(context => context.GetInstance<ISessionFactory>().OpenSession());
// Nhibernate SessionFactory
For<ISessionFactory>().Singleton().Use(NhibernateHelper.CreateSessionFactory());
}`
Here is my nhibernate http module:
public class NHibernateModule : IHttpModule
{
private IUnitOfWork _unitOfWork;
public void Init(HttpApplication context)
{
context.BeginRequest += ContextBeginRequest;
context.EndRequest += ContextEndRequest;
}
private void ContextBeginRequest(object sender, EventArgs e)
{
_unitOfWork = ObjectFactory.GetInstance<IUnitOfWork>();
}
private void ContextEndRequest(object sender, EventArgs e)
{
try { _unitOfWork.Commit(); }
catch { _unitOfWork.Rollback(); }
finally { Dispose(); }
}
public void Dispose()
{
if (_unitOfWork != null)
_unitOfWork.Dispose();
}
}
UserRepository needs a constructor that takes in the IUnitOfWork and passes it to the BaseRepository constructor. Currently, UserRepository is using the parameterless constructor of BaseRepository, so no IUnitOfWork is injected. Get rid of the parameterless constructor, and make sure all derived types pass the IUnitOfWork to the base.