Castle Windsor Constructor Injection - c#

I have been trying to get Castle Windsor to inject my DB Context to my controllers I have been following the tutorials on the Castle Windsor website
my code is as follows
Bootstrapper
internal class IOCContainerBootstrap
{
private static IWindsorContainer container;
public static void Configure()
{
container = new WindsorContainer()
.Install(FromAssembly.This());
var controllerFactory = new GravityClimbingControllerFactory(container.Kernel);
ControllerBuilder.Current.SetControllerFactory(controllerFactory);
}
#region IDisposable Members
public static void Dispose()
{
container.Dispose();
}
#endregion
}
Installers
public class ControllersInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(Classes.FromThisAssembly()
.BasedOn<IController>()
.LifestyleTransient());
container.Register(Component.For<DbContext>().ImplementedBy<GravityClimbingEntities>());
}
}
public class APIInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(Classes
.FromThisAssembly()
.BasedOn<IHttpController>()
.ConfigureFor<ApiController>(c => { c.PropertiesIgnore(pi => false); })
.LifestyleTransient());
}
}
And finally
My API Controller
public class ArticalsController : ApiController
{
private readonly DbContext _context;
private readonly Db.Repositories.ArticalRepository repository;
public ArticalsController(DbContext context)
{
_context = context;
repository = new Db.Repositories.ArticalRepository(context);
}
[HttpGet]
public string HelloWorld()
{
return "Hello.world";
}
}
When I Debug I get no errors and it says it can resolve the dependency
But when i try to call the API controller I get the following Error Message
{
"Message" : "An error has occurred.",
"ExceptionMessage" : "Type 'ArticalsController' does not have a default constructor",
"ExceptionType" : "System.ArgumentException"
}
Is there something silly I am doing wrong, that I cannot see?

For people who are facing the same issue I found the issue.
Castle Windsor didn't know about the IHTTPControler (Base for the APIController) so i needed to create an IHttpControllerActivator and attach it to the GlobalConfiguration.Configuration.Services
I found this link to enable this here

Related

unity dependency error -make sure that the controller has a parameterless public constructor

Sorry i am new to IOC concepts. I have been trying to implement Unity.WebAPI (5.3.0.) in my web api project but getting following error;
An error occurred when trying to create a controller of type 'TransactionController'. Make sure that the controller has a parameterless public constructor
UnityResolver Class
public class UnityResolver : IDependencyResolver
{
protected IUnityContainer container;
public UnityResolver(IUnityContainer container)
{
if (container == null)
{
throw new ArgumentNullException("container");
}
this.container = container;
}
public object GetService(Type serviceType)
{
try
{
return container.Resolve(serviceType);
}
catch (ResolutionFailedException)
{
return null;
}
}
public IEnumerable<object> GetServices(Type serviceType)
{
try
{
return container.ResolveAll(serviceType);
}
catch (ResolutionFailedException)
{
return new List<object>();
}
}
public IDependencyScope BeginScope()
{
var child = container.CreateChildContainer();
return new UnityResolver(child);
}
public void Dispose()
{
container.Dispose();
}
}
Web Api Config
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
var container = new UnityContainer();
// register all your components with the container here
// it is NOT necessary to register your controllers
// e.g. container.RegisterType<ITestService, TestService>();
container.RegisterType<IFService, FService>(new HierarchicalLifetimeManager());
container.RegisterType<IMService, MService>(new HierarchicalLifetimeManager());
container.RegisterType<ITransactionService, TransactionService>(new HierarchicalLifetimeManager());
container.RegisterType<IMRepository, MRepository>();
config.DependencyResolver = new UnityResolver(container);
}
}
Global.asax
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
Controller
public class TransactionController : ApiController
{
private readonly ITransactionService _transactionService;
private readonly IMService _mService;
/// <summary>
/// Public constructor to initialize transaction service instance
/// </summary>
public TransactionController(ITransactionService transactiontService, IMService mService)
{
_mService = mService;
_transactionService = transactiontService;
}
[HttpGet]
public IHttpActionResult IsApiAlive()
{
return Ok();
}
TransactionService Class constructor
private readonly IMRepository _mRepository;
public TransactionService(IMRepository mRepository)
{
_mRepository = mRepository;
}
Check to make sure that all dependencies for the object graphs have been registered so that they can be resolved correctly.
You are most likely missing a dependency registration.
For TransactionService, you are passing/injecting the implementations in the constructors
public TransactionService(MRepository mRepository, FService fService) {
_mRepository = mRepository;
_fservice = fService;
}
while you only registered the interfaces.
container.RegisterType<IFService, FService>(new HierarchicalLifetimeManager());
container.RegisterType<IMService, MService>(new HierarchicalLifetimeManager());
container.RegisterType<ITransactionService, TransactionService>(new HierarchicalLifetimeManager());
container.RegisterType<IMRepository, MRepository>();
The resolver will do the actual initialization and injection of the implementations based on the known dependencies.
Change
public TransactionService(MRepository mRepository, FService fService)
To rely on the registered interfaces
private readonly IMRepository mRepository;
private readonly IFService fService;
public TransactionService(IMRepository mRepository, IFService fService) {
this.mRepository = mRepository;
this.fservice = fService;
}
every class involved in creating/resolving the controller needs to be checked to make sure that their dependencies can be resolved without error.

Unity Dependency injection on the same project for web api and mvc

At first I started the project with asp.net mvc and unity.mvc for DI, then wanted to add web api to the same project and installed unity.webapi but with that now unity dependency injection is unable to inject service instances to the ApiControllers however the controller class are working.
UnityConfig.cs
public static class UnityConfig
{
private static Lazy<IUnityContainer> container =
new Lazy<IUnityContainer>(() =>
{
var container = new UnityContainer();
RegisterTypes(container);
return container;
});
public static IUnityContainer Container => container.Value;
public static void RegisterTypes(IUnityContainer container)
{
container.RegisterType<IEmployeeService, EmployeeService>();
container.RegisterType<IRepository<Employee>, Repository<Employee>>();
}
}
ApiController.cs
public class EmployeeApiController : ApiController
{
private readonly IEmployeeService _employeeService;
public EmployeeApiController(IEmployeeService employeeService)
{
_employeeService = employeeService;
}
public EmployeeApiController(){}
// GET: api/EmployeeApi
public IEnumerable<Employee> Get()
{
var a = _employeeService.GetAll();
return a;
}
}
Global.asax.cs
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
}
On the get action of apicontroller the IService throughs a null pointer exception.
Web API defines the following interfaces for resolving dependencies:
public interface IDependencyResolver : IDependencyScope, IDisposable
{
IDependencyScope BeginScope();
}
public interface IDependencyScope : IDisposable
{
object GetService(Type serviceType);
IEnumerable<object> GetServices(Type serviceType);
}
As you pointed out in your comment, the Unity.WebApi nuget package provides this implementation which you can just register in the application startup.
For full reference:
public static class UnityConfig
{
public static void RegisterComponents()
{
var container = new UnityContainer();
GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);
}
}
public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
UnityConfig.RegisterComponents();
}
}
Found the solution:
added the following line on the UnityConfig.cs:
public static void RegisterTypes(IUnityContainer container)
{
//Add this line
GlobalConfiguration.Configuration.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(container);
container.RegisterType<IEmployeeService, EmployeeService>();
container.RegisterType<IRepository<Employee>, Repository<Employee>>();
}

No component for supporting the service HomeController was found - Castle Windsor error

I read this article about Casle Windsor. So I have classes BusinessLogicInstaller.cs, ControllersInstaller, IocContainer and WindsorControllerFactory. Here is the example:
public class ControllersInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(AllTypes.FromThisAssembly()
.Pick().If(t => t.Name.EndsWith("Controller"))
.Configure(configurer => configurer.Named(configurer.Implementation.Name))
.LifestylePerWebRequest());
}
}
public class BusinessLogicInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(
Component
.For<IUser>()
.ImplementedBy<User>());
}
}
public static class IocContainer
{
private static IWindsorContainer _container;
public static void Setup()
{
_container = new WindsorContainer().Install(FromAssembly.This());
WindsorControllerFactory controllerFactory = new WindsorControllerFactory(_container.Kernel);
ControllerBuilder.Current.SetControllerFactory(controllerFactory);
}
}
public class WindsorControllerFactory : DefaultControllerFactory
{
private readonly IKernel _kernel;
public WindsorControllerFactory(IKernel kernel)
{
this._kernel = kernel;
}
public override void ReleaseController(IController controller)
{
_kernel.ReleaseComponent(controller);
}
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);
}
}
In the Global.asax class I have
public class MvcApplication : HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
// Add this line to Application_Start in Global.asax.cs to setup the IoC Container.
IocContainer.Setup();
}
}
The problem is in class WindsorControllerFactory.cs in this line of code:
return (IController)_kernel.Resolve(controllerType);
The error is No component for supporting the service Controllers.HomeController was found. Where is the error?
I found solution... First of all, I didn't mention one big difference in my MVC project(because I didn't know why is that important) - I have separate assembly for Controllers. So, there was an error in this part of the code in ControllerInstallers.cs :
.FromThisAssembly()
It should be:
.FromAssemblyNamed("Controllers")
I have to say thank you to #Jan Muncinsky because of your answer and because of your hint to a class where the problem was.

Web Api OWIN Host with Unity

I'm trying to implement UNITY on my WebApi2 application.
The problem is that I'm using an existing SqlConnection, depending on an identifier found in the URL of the resource.
So I need the identifier provided in the request uri, to create my context with.
Is it possible to get the {dbIdentifier} from the request URI, and parse it into the constructor of MyRepo?
The Request usi will look like: /api/{dbIdentifier}/{controller}/{id}
The structure looks like...
Request POST /api/myDbIdentifier/my/ + PAYLOAD data
Controller:
public class MyController : ApiController
{
private readonly IRepo _repo;
public MyController(IRepo repo)
{
_repo = repo;
}
}
Repo:
public class MyRepo : IRepo
{
private readonly MyContext _context;
public MyRepo(string dbIdentifier)
{
_context = new MyContext(GetConnection(dbIdentifier));
}
public void Insert(string s)
{
//Inserting string in context and save changes
}
private DbConnection(string id)
{
//psudo find connecion from pool, and return instance of DbConnection...
}
}
public interface IRepo
{
void Insert(string s);
}
Context:
public class MyContext : DbContext
{
public MyContext(DbConnection exitingConnection) : base(existingConnection, true)
{ }
}
Btw, it's my first time playing around with WebApi and Unity, so please bear with my ignorance.
UPDATED Unity part of my code...
UnityResolver (taken from https://learn.microsoft.com/en-us/aspnet/web-api/overview/advanced/dependency-injection):
public class UnityResolver : IDependencyResolver
{
protected IUnityContainer Container;
public UnityResolver(IUnityContainer container)
{
if (container == null)
{
throw new ArgumentNullException(nameof(container), "Please provider an IUnityContainer.");
}
Container = container;
}
public void Dispose()
{
Container.Dispose();
}
public object GetService(Type serviceType)
{
try
{
return Container.Resolve(serviceType);
}
catch (ResolutionFailedException)
{
return null;
}
}
public IEnumerable<object> GetServices(Type serviceType)
{
try
{
return Container.ResolveAll(serviceType);
}
catch (Exception)
{
return new List<object>();
}
}
public IDependencyScope BeginScope()
{
return new UnityResolver(Container.CreateChildContainer());
}
}
Unity Register part in my startup:
public static void Register(HttpConfiguration config)
{
// Configuring DI Container fo IoC (Invert of Control)
var container = new UnityContainer();
container.RegisterType<IRepo, MyRepo>(new HierarchicalLifetimeManager());
config.DependencyResolver = new UnityResolver(container);
}
You can try the following:
1)Create a DelegatingHandler where you can access HtppRequestMessage.RequestUri
2)Extract dbIdentifier from Uri
3)Wrap dbIdentifier with a class (e.g. DbIdentifier) and register it in unity using HierarchicalLifetimeManager
4)Remember to register handler in owin:
httpConfiguration.MessageHandlers.Add(new DbIdentifierHandler());
EDIT.
You can look into this post to find some inspiration :
How to pass Owin context to a Repo being injected into Api controller

Castle Windsor won't inject Logger in a property!

I try to inject log4net in a ILogger property of my service class but the property is always NULL!
I've seen this topic but it doesn't help me!
How can I get Castle Windsor to automatically inject a property?
this is Program.cs
CastleContainer.Instance
.Install(
new RepositoriesInstaller(),
new PersistenceInstaller(),
new LoggerInstaller(),
new FormInstaller(),
new ServiceInstaller()
);
FrmStart form1 = CastleContainer.Resolve<FrmStart>(new {Id="666" });
I use log4net.config external file and this is my installer:
public class LoggerInstaller : IWindsorInstaller
{
#region IWindsorInstaller Members
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.AddFacility("logging", new LoggingFacility(LoggerImplementation.Log4net, "log4net.config"));
}
#endregion
}
This is the class contains the property I want Windsor to inject:
public partial class FrmStart : Form
{
private EventService EventService;
private ILogger logger = NullLogger.Instance;
public ILogger Logger
{
get { return logger; }
set { logger = value; }
}
public FrmStart(EventService eventService, string Id)
: this()
{
Logger.Debug("xxx");
this.EventService = eventService;
this.id = Id;
}
Note that "eventService" and "Id" in the constructor are correctly injected!
If I try to inject the Logger in the constructor it works and I've the Logger object:
{log4net.Repository.Hierarchy.DefaultLoggerFactory+LoggerImpl}! :-(
I've tried to create a public property for EventService and Windsor can inject it properly! So I think the problem is related only to the ILogger interface.
I prepared a simple full-code example here:
using Castle.Core.Logging;
using Castle.Facilities.Logging;
using Castle.MicroKernel.Registration;
using Castle.MicroKernel.SubSystems.Configuration;
using Castle.Windsor;
namespace IocTest
{
public class LoggerInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.AddFacility("logger", new LoggingFacility(LoggerImplementation.Log4net, "log4net.config"));
}
}
public class LogicInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(AllTypes.FromThisAssembly()
.Pick()
.If(t => t.Name.StartsWith("Logic"))
.Configure((c => c.LifeStyle.Transient)));
}
}
class Program
{
static void Main(string[] args)
{
IWindsorContainer container = new WindsorContainer();
container.Install(
new LoggerInstaller(),
new LogicInstaller()
);
LogicClass1 logic1 = container.Resolve<LogicClass1>();
LogicClass2 logic2 = container.Resolve<LogicClass2>();
}
}
public class LogicClass1
{
private ILogger logger = NullLogger.Instance;
public ILogger Logger
{
get { return logger; }
set { logger = value; }
}
public LogicClass1()
{
logger.Debug("Here logger is NullLogger!");
}
}
public class LogicClass2
{
public LogicClass2(ILogger logger)
{
logger.Debug("Here logger is properly injected!");
}
}
}
What's wrong?
A problem is where you are checking it:
public ILogger Logger
{
get { return logger; }
set { logger = value; }
}
public LogicClass1()
{
logger.Debug("Here logger is NullLogger!");
}
The property injection will not happen until after the constructor is run, so checking the property value in the constructor will never show the value you are expecting
I was having the same problem. It was always null.
I managed to solve the problem by injecting the logger in the constructor this way:
public ILogger logger;
public MyController(ILogger logger)
{
this.logger = logger;
logger.Info("Something");
}
You could also initialize your Logger by using:
public ILogger Logger { get; set; }
public MyController()
{
Logger = NullLogger.Instance;
}

Categories