Constructor DI + Unity 2.0 + issue with resolving dependency - asp.net-mvc-3

Controller:
public class HomeController : Controller
{
IEmployeeTask _employeeTask;
public HomeController()
{
_employeeTask = new UnityContainer().Resolve<IEmployeeTask>();
}
public HomeController(IEmployeeTask employeeTask)
{
_employeeTask = employeeTask;
}
public ActionResult Index()
{
ViewBag.Message = "Welcome to ASP.NET MVC!";
return View();
}
public ActionResult GetAndDisplayEmployee()
{
return View();
}
[HttpPost]
public ActionResult GetAndDisplayEmployee(int empid)
{
return View(_employeeTask.GetEmployeeModelFromService(empid));
}
}
Global.asax.cs:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
var container = new UnityContainer();
container.RegisterType<IEmployeeModelMap, EmployeeModelMap>();
container.RegisterType<IEmployeeService, EmployeeService>();
container.RegisterType<IEmployeeTask, EmployeeTask>();
container.RegisterType<IEmployee, Employee>();
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}
Unity Dependency Resolver:
public class UnityDependencyResolver : IDependencyResolver
{
readonly IUnityContainer _container;
public UnityDependencyResolver(IUnityContainer container)
{
this._container = container;
}
public object GetService(Type serviceType)
{
try
{
return _container.Resolve(serviceType);
}
catch
{
return null;
}
}
public IEnumerable<object> GetServices(Type serviceType)
{
try
{
return _container.ResolveAll(serviceType);
}
catch
{
return new List<object>();
}
}
}
Employee Task class:
public class EmployeeTask: IEmployeeTask
{
IEmployeeService _employeeService;
IEmployeeModelMap _employeeModelMap;
public EmployeeTask(IEmployeeService employeeService, IEmployeeModelMap employeeModelMap)
{
_employeeService = employeeService;
_employeeModelMap = employeeModelMap;
}
public EmployeeViewModel GetEmployeeModelFromService(int empId)
{
return _employeeModelMap.ToModel(_employeeService.GetEmployeeFromEntities(empId));
}
}
Now, i have used unity 2.0 application block. Tried to resolve the dependency of the controller using unity with out using Custom Controller factory.
I am stuck with below error.
The current type, DataProviderInfrastructure.IEmployeeTask, is an
interface and cannot be constructed. Are you missing a type mapping?

I don't use Unity, but my guess would be that it attempts to use your parameterless constructor where you try to resolve the dependency. Creating this constructor is very very wrong. First - it defeats the purpose of having dependency injection and second - you create new container inside - which will be empty so it obviously can't resolve any dependencies. Try removing this from your code:
public HomeController()
{
_employeeTask = new UnityContainer().Resolve<IEmployeeTask>();
}

Related

Ninject Interception in WebAPI and parameterless constructor failing

I have an MVC4 site that uses both MVC and WebAPI in it. All was going well till I tried to change my classes to have a cross cutting AOP class that would help with caching data. I am now finding that when I call a method that does not have the InterceptAttribute on it, it will crash because Ninject didn't inject with a parameter, and it fails.
My BLL class looks like this:
public class FooBLL
{
#region Private Variables
private readonly IDAL _context;
#endregion
#region Constructor
public Foo(IDAL context)
{
_context = context;
}
#endregion
#region Public Methods
public List<Bar> GetAllBars()
{
return _context.GetAllBars();
}
public List<Bar> GetTwoBars()
{
return _context.GetTwoBars();
}
#endregion
}
My WebApi Controller looks like this:
public class FooController : ApiController
{
#region Private Variables
private readonly FooBLL _fooBll;
#endregion
#region Constructor
public FooController(FooBLL fooBll)
{
_fooBll = fooBll;
}
#endregion
#region Public Methods
#region Estimate Types
#region Get
public List<Bar> GetAllBars()
{
return _fooBll.GetAllBars();
}
public List<Bar> GetTwoBars()
{
return _fooBll.GetTwoBars();
}
#endregion
#endregion
#endregion
}
In my Website, I created the following Ninject classes for resolving the controllers:
public class NinjectRegistrations : NinjectModule
{
public override void Load()
{
Kernel.Bind<IDAL>().To<DAL>().InSingletonScope();
}
}
public class NinjectDependencyResolver : NinjectDependencyScope, IDependencyResolver, System.Web.Mvc.IDependencyResolver
{
private readonly IKernel kernel;
public NinjectDependencyResolver(IKernel kernel)
: base(kernel)
{
this.kernel = kernel;
}
public IDependencyScope BeginScope()
{
return new NinjectDependencyScope(this.kernel.BeginBlock());
}
}
public class NinjectDependencyScope : IDependencyScope
{
private IResolutionRoot resolver;
internal NinjectDependencyScope(IResolutionRoot resolver)
{
Contract.Assert(resolver != null);
this.resolver = resolver;
}
public void Dispose()
{
var disposable = this.resolver as IDisposable;
if (disposable != null)
{
disposable.Dispose();
}
this.resolver = null;
}
public object GetService(Type serviceType)
{
if (this.resolver == null)
{
throw new ObjectDisposedException("this", "This scope has already been disposed");
}
return this.resolver.TryGet(serviceType);
}
public IEnumerable<object> GetServices(Type serviceType)
{
if (this.resolver == null)
{
throw new ObjectDisposedException("this", "This scope has already been disposed");
}
return this.resolver.GetAll(serviceType);
}
}
In Global.asax I then register this resolver:
NinjectHelper.Kernel = new StandardKernel(modules);
var ninjectResolver = new NinjectDependencyResolver(NinjectHelper.Kernel);
DependencyResolver.SetResolver(ninjectResolver); // MVC
GlobalConfiguration.Configuration.DependencyResolver = ninjectResolver; // Web API
//Register Filter Injector
GlobalConfiguration.Configuration.Services.Add(typeof(System.Web.Http.Filters.IFilterProvider), new NinjectWebApiFilterProvider(NinjectHelper.Kernel));
Things were fine till I added the attribute Cache using Ninject.Extensions.Interception.Attributes.InterceptAttribute.
The class now looks like this (note that I added a parameterless constructor and marked one of the methods as virtual, these are both required for the Interception to work):
public class FooBLL
{
#region Private Variables
private readonly IDAL _context;
#endregion
#region Constructor
public Foo(IDAL context)
{
_context = context;
}
public Foo()
{
}
#endregion
#region Public Methods
public List<Bar> GetAllBars()
{
return _context.GetAllBars();
}
[Cache(DefaultTimeoutMinutes = 20)]
public virtual List<Bar> GetTwoBars()
{
return _context.GetTwoBars();
}
#endregion
}
Now on the WebAPI controller, when I call GetToBars(the method with the Intercept Attribute), everything still works fine.
However, when I call GetAllBars(the method that doesn't have the Intercept Attribute), I fail with an exception that _context is null.
Any help would be greatly appreciated.
Ben

"The type IUnitOfWork does not have an accessible constructor" with Umbraco 6.1, UmbracoApiController (Web API) & Dependency Injection (Unity)

I am using Umbraco 6.1 with an UmbracoApiController which has a IUnitOfWork injected into it's constructor. To inject the dependencies, I am using Unity, like I have in the past with standard Web API projects. Normally, I set unity up in the Global.asax.cs. As Umbraco does not have this I have created my own UmbracoEvents handler, which inherits from IApplicationEventHandler, and has the methods:
OnApplicationInitialized
OnApplicationStarting
OnApplicationStarted
ConfigureApi
In the OnApplicationStarted method I set up my EF database, db initializer etc and call ConfigureApi to set up Unity. My OnApplication Started and ConfigureApi methods looks like this:
public void OnApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
{
_applicationContext = applicationContext;
_umbracoApplication = umbracoApplication;
_contentService = ApplicationContext.Current.Services.ContentService;
this.ConfigureApi(GlobalConfiguration.Configuration);
Database.SetInitializer(null);
PropertySearchContext db = new PropertySearchContext();
db.Database.Initialize(true);
}
private void ConfigureApi(HttpConfiguration config)
{
var unity = new UnityContainer();
unity.RegisterType<PropertiesApiController>();
unity.RegisterType<IUnitOfWork, UnitOfWork>(new HierarchicalLifetimeManager());
config.DependencyResolver = new IoCContainer(unity);
}
My Controller code:
public class PropertiesApiController : UmbracoApiController
{
private readonly IUnitOfWork _unitOfWork;
public PropertiesApiController(IUnitOfWork unitOfWork)
{
if(null == unitOfWork)
throw new ArgumentNullException();
_unitOfWork = unitOfWork;
}
public IEnumerable GetAllProperties()
{
return new[] {"Table", "Chair", "Desk", "Computer", "Beer fridge"};
}
}
My Scope Container/IoC Container code: (as per http://www.asp.net/web-api/overview/extensibility/using-the-web-api-dependency-resolver)
public class ScopeContainer : IDependencyScope
{
protected IUnityContainer container;
public ScopeContainer(IUnityContainer container)
{
if (container == null)
{
throw new ArgumentNullException("container");
}
this.container = container;
}
public object GetService(Type serviceType)
{
if (container.IsRegistered(serviceType))
{
return container.Resolve(serviceType);
}
else
{
return null;
}
}
public IEnumerable<object> GetServices(Type serviceType)
{
if (container.IsRegistered(serviceType))
{
return container.ResolveAll(serviceType);
}
else
{
return new List<object>();
}
}
public void Dispose()
{
container.Dispose();
}
}
public class IoCContainer : ScopeContainer, IDependencyResolver
{
public IoCContainer(IUnityContainer container)
: base(container)
{
}
public IDependencyScope BeginScope()
{
var child = this.container.CreateChildContainer();
return new ScopeContainer(child);
}
}
My IUnitOfWork code:
public interface IUnitOfWork : IDisposable
{
GenericRepository<Office> OfficeRepository { get; }
GenericRepository<Property> PropertyRepository { get; }
void Save();
void Dispose(bool disposing);
void Dispose();
}
My UnitOfWork implementation:
public class UnitOfWork : IUnitOfWork
{
private readonly PropertySearchContext _context = new PropertySearchContext();
private GenericRepository<Office> _officeRepository;
private GenericRepository<Property> _propertyRepository;
public GenericRepository<Office> OfficeRepository
{
get
{
if (this._officeRepository == null)
{
this._officeRepository = new GenericRepository<Office>(_context);
}
return _officeRepository;
}
}
public GenericRepository<Property> PropertyRepository
{
get
{
if (this._propertyRepository == null)
{
this._propertyRepository = new GenericRepository<Property>(_context);
}
return _propertyRepository;
}
}
public void Save()
{
_context.SaveChanges();
}
private bool disposed = false;
public virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
_context.Dispose();
}
}
this.disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
I have used unity/DI with MVC4/WebAPI controllers and this implementation of UnitOfWork many times before without issue, so I'm thinking it's Umbraco specific.
I have also debugged the application and made sure that it hits OnApplicationStarted and that its parameters are not null.
The GetAllProperties method in the controller is just a test method to make sure it is all working fine, however, when I try and access this action I get the error:
"The type IUnitOfWork does not have an accessible constructor"
Does anyone have experience with using Umbraco 6.1 and it's UmbracoApiController with dependency injection/Unity?
Also, on an unrelated note, is there a way to return JSON instead of XML in the action? In Web API you would just define the formatter in the WebApi.config but there is none in Umbraco.
Thanks,
Justin
In case you haven't found a solution to your problem? Download this nuget package and right after building your unity container:
GlobalConfiguration.Configuration.DependencyResolver =
new Unity.WebApi.UnityDependencyResolver(Bootstrapper.Container);
Notice the namespace which is different than Unity.Mvc4.UnityDependencyResolver.

How should the GetService method in IDependencyResolver implementation for Unity look like?

I'd like to use Unity as an IoC container for an ASP.NET MVC 3 app but am having trouble with my UnityDependecyResolver class. It currently looks like this (copied from somewhere on the web as I don't think Unity itself comes with this):
public class UnityDependencyResolver : IDependencyResolver
{
readonly IUnityContainer _container;
public UnityDependencyResolver(IUnityContainer container)
{
this._container = container;
}
public object GetService(Type serviceType)
{
try
{
return _container.Resolve(serviceType);
}
catch
{
return null;
}
}
public IEnumerable<object> GetServices(Type serviceType)
{
try
{
return _container.ResolveAll(serviceType);
}
catch
{
return new List<object>();
}
}
}
However, I get this runtime error when trying to visit any controller:
The IControllerFactory 'System.Web.Mvc.DefaultControllerFactory' did not return a controller for the name 'Account'.
This StructureMap article suggests that I should amend the GetService method, however, I'm quite new to both MVC and Unity and I'm not sure how exactly should it look like.
Have a look at the Unity.MVC project on codeplex.
This is my implementation and for me it works
public class UnityResolver : IDependencyResolver
{
private readonly IUnityContainer _container;
public UnityResolver(IUnityContainer container)
{
_container = container;
}
public object GetService(Type serviceType)
{
if (typeof(IController).IsAssignableFrom(serviceType))
{
return _container.CreateChildContainer().Resolve(serviceType);
}
if (_container.IsRegistered(serviceType))
{
return _container.CreateChildContainer().Resolve(serviceType);
}
return null;
}
public IEnumerable<object> GetServices(Type serviceType)
{
return _container.CreateChildContainer().ResolveAll(serviceType);
}
}

Resolving MVC Controller with WindsorControllerFactory

I'm new to Windsor, so
Here is my installer:
public class ControllersInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(FindControllers().Configure(ConfigureControllers()));
}
private ConfigureDelegate ConfigureControllers()
{
return c => c.LifeStyle.Transient;
}
private BasedOnDescriptor FindControllers()
{
return AllTypes.FromThisAssembly()
.BasedOn<IController>()
.If(Component.IsInSameNamespaceAs<HomeController>())
.If(t => t.Name.EndsWith("Controller"));
}
}
And factory:
public class WindsorControllerFactory : DefaultControllerFactory
{
private readonly IKernel _kernel;
public WindsorControllerFactory(IKernel kernel)
{
_kernel = kernel;
}
public override void ReleaseController(IController controller)
{
_kernel.ReleaseComponent(controller);
}
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
try
{
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);
}
catch(Exception ex)
{
return null;
}
}
}
All controllers which inherits from Controller are resolved well. But when I try to instantiate something like this:
public class ArticleController : RestController<Article>
{
protected override JsonResult Create(Article item)
{
...
}
}
RestController also inherits from Controller
it throws
The IControllerFactory 'TheStorage.Web.Factories.WindsorControllerFactory' did not return a controller for the name 'Article'
What I'm doing wrong?
The error you're getting is due to the try/catch that you put in the factory. You should not be doing that.
Now, what is happening most likely, is your container can not resolve your controller, likely either because it has unresolvable dependencies, or it doesn't get registered (maybe you put it in wrong namespace)?
Once you let it fail, Windsor will tell you exactly what the problem is.

Castle Windsor: master controller not resolving the registered components in the container

Having the code below in my Global.asax.cs and two controller (one based on a the other: MasterController) I don't seem to find how can I resolve the repository register in my WindsorContainer from the MasterController... the same applies in the HomeController and works perfectly... what am I doing wrong?
Global.asax.cs:
private IWindsorContainer _container;
protected void Application_Start()
{
InitializeContainer();
RegisterRoutes(RouteTable.Routes);
}
protected void Application_End()
{
this._container.Dispose();
}
protected void Application_EndRequest()
{
if (_container != null)
{
var contextManager = _container.Resolve<IContextManager>();
contextManager.CleanupCurrent();
}
}
private void InitializeContainer()
{
_container = new WindsorContainer();
ControllerBuilder.Current.SetControllerFactory(new WindsorControllerFactory(_container));
// Register context manager.
_container.Register(
Component.For<IContextManager>()
.ImplementedBy<EFContextManager>()
.LifeStyle.Singleton
.Parameters(
Parameter.ForKey("connectionString").Eq(ConfigurationManager.ConnectionStrings["ProvidersConnection"].ConnectionString)
)
);
//Products repository
_container.Register(
Component.For<IProductRepository>()
.ImplementedBy<ProductRepository>()
.LifeStyle.Singleton
);
// Register all MVC controllers
_container.Register(AllTypes.Of<IController>()
.FromAssembly(Assembly.GetExecutingAssembly())
.Configure(c => c.LifeStyle.Transient)
);
}
Controller base:
public class MasterController : Controller
{
private IProductRepository _productRepository;
public ProductController(IProductRepository product)
{
_productRepository = product;
}
public ActionResult Index()
{
ViewData["product"] = _productRepository.FindOne(123);
return View();
}
}
Controller based on MasterController:
public class ProductController : MasterController
{
private IProductRepository _productRepository;
public ProductController(IProductRepository product)
{
_productRepository = product;
}
public ActionResult Search(int id)
{
ViewData["product"] = _productRepository.FindOne(id);
return View();
}
}
It is working as expected now and the ViewDatas are accessible from any controller/view.
First I created a public class where I store my Windsor container so it can be accessed from any controller:
public static class IOCcontainer
{
public static IWindsorContainer Container { get; set; }
}
Then in my global.asax.cs I have:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
InitializeContainer();
}
private void InitializeContainer()
{
_container = new WindsorContainer();
// Register context manager.
_container.Register(
Component.For<IContextManager>()
.ImplementedBy<EFContextManager>()
.LifeStyle.Singleton
.Parameters(
Parameter.ForKey("connectionString").Eq(ConfigurationManager.ConnectionStrings["ProvidersConnection"].ConnectionString)
)
);
//Products repository
_container.Register(
Component.For<IProductRepository>()
.ImplementedBy<ProductRepository>()
.LifeStyle.Singleton
);
// Register all MVC controllers
_container.Register(AllTypes.Of<IController>()
.FromAssembly(Assembly.GetExecutingAssembly())
.Configure(c => c.LifeStyle.Transient)
);
IOCcontainer.Container = _container; //set the container class with all the registrations
ControllerBuilder.Current.SetControllerFactory(new WindsorControllerFactory(_container));
}
So now in my master controller I can use:
public class MasterController : Controller
{
private IProductRepository g_productRepository;
public MasterController() : this(null,null,null,null,null)
{
}
public MasterController(IProductRepository productRepository)
{
g_productRepository = productRepository ?? IOCcontainer.Container.Resolve<IProductRepository>();
}
//I don't use an action here, this will make execute it for any action in any controller
protected override void OnActionExecuting(ActionExecutingContext context)
{
if (!(context.ActionDescriptor.ActionName.Equals("Index") && context.Controller.ToString().IndexOf("Home")>0)) {
//I now can use this viewdata to populate a dropdownlist along the whole application
ViewData["products"] = g_productRepository.GetProducts().ToList().SelectFromList(x => x.Id.ToString(), y => y.End.ToShortDateString());
}
}
}
Then the rest of controllers:
//will be based on MasterController
public class AboutController : MasterController
{
}
public ActionResult Index()
{
return View();
}
etc...
Probably not the most elegant way to do it but it will do until I find a better way or someone else brighten my mind up!

Resources