I have simple controller with one dependency
public TestController(ITestFacade testFacade)
{
_testFacade = testFacade;
}
and simple facade
public class TestFacade : ITestFacade
{
public TestFacade()
{
throw new Exception("Test");
}
}
I have Unity resolver and registration
public static void RegisterDependencies(IUnityContainer container)
{
container.RegisterType<ITestFacade, TestFacade>();
}
UnityResolver is common as found everywhere. Nothing custom.
public object GetService(Type serviceType)
{
try
{
return _container.Resolve(serviceType);
}
catch (ResolutionFailedException)
{
// Here in one of Inner Exceptions is my Facade exception, but I want to get it later
return null;
}
}
Please consider this as test scenario. Facade in constructor should fail for any reason. It is not important now.
Running application results in exception:
An error occurred when trying to create a controller of type 'TestController'. Make sure that the controller has a parameterless public constructor.
Ok, this is because of error in constructor of Facade when resolver is not able to get instance and activator in controller failed.
My question is - is there any way how to catch this exception in IHttpControllerActivator or somewhere?
I can try catch code in Facade constructor and log it somehow, but why this exception is ignored after resolver.
Related
I use castle to resolve dependencies through constructor injection.
My problem is that the constructor for a service might use 3rd party plugin code.
If this plugin code throws an exception, it is wrapped in a known exception, say "KnownException".
I have a special exception policy to log and handle the "KnownException".
The problem is that if the Castle Windsorcontainer resolve encounters an exception it is wrapped in a 'Castle.MicroKernel.ComponentActivator.ComponentActivatorException'.
Is there a way to avoid this, and just let the 'KnownException' propagate?
A simple scenario:
public class KnownException : Exception
{
}
// registerd in castle
public class DetailViewModel
{
public DetailViewModel(Selector thirdPartySelector)
{
thirdPartySelector.GetElements(); // might throw known exception
}
}
// registered as TypedFactory in Castle
public interface IViewModelFactory
{
DetailViewModel Create(Selector thirdPartySelector);
}
public class MasterViewModel
{
private readonly IViewModelFactory viewModelFactory;
private readonly Selector selector;
public MasterViewModel(IViewModelFactory viewModelFactory)
{
this.viewModelFactory = viewModelFactory;
selector = Mock.Of<Selector>(); // for illustration purpose only. Creation is more elaborate, and not relly a problem here.
}
public void OnAddDetailed()
{
try
{
var vm = viewModelFactory.Create(selector);
// adding detailed view model.
}
catch (KnownException e)
{
// Log and continue
}
}
}
}
Apparently the ComponentActivatorException wraps the initial exception before being thrown when Castle tries to resolve the component. There is no way to bypass this behavior.
Your best bet would be to catch the ComponentActivatorException and throw its InnerException in order to find again a known type for your error handling
To avoid castle using the component activator, you can register your component with a UsingFactoryMethod ie:
Component.For<IFoo>().UsingFactoryMethod(k => new Foo())
There are some drawbacks:
If Foo has dependencies you will need to resolve these from the container yourself, and interceptors won't work. If needed OnDestroy can help with releasing the dependencies.
I solved this by decorating the factory, catch the ComponentActivatorException and throw the InnerException.
But I'm wondering, if this should be solved by the container, as if I'm using the factory, I should not be aware there is a container outside. But if the create method throws a CastleWindsor Exception, that is not the case.
My solution:
[TestMethod]
public void CastleWindsor_FactoryThrows_MyException()
{
WindsorContainer Container = new WindsorContainer();
Container.AddFacility<TypedFactoryFacility>();
Container.Register(Component.For<IMyFactory>().ImplementedBy<MyFactoryDecorator>());
Container.Register(Component.For<IMyFactory>().AsFactory());
Container.Register(Component.For<MyClass>().LifestyleTransient());
var factory = Container.Resolve<IMyFactory>();
try
{
factory.Create();
}
catch (Exception e)
{
Assert.AreEqual(e.GetType(), typeof(MyException));
}
}
public class MyFactoryDecorator : IMyFactory
{
IMyFactory factory;
public MyFactoryDecorator(IMyFactory aFactory)
{
factory = aFactory;
}
MyClass IMyFactory.Create() => handleComponentActivatorException(() => factory.Create());
T handleComponentActivatorException<T>(Func<T> action)
{
try
{
return action();
}
catch (ComponentActivatorException e)
{
throw e.InnerException.InnerException;
}
}
}
public interface IMyFactory
{
MyClass Create();
}
public class MyException : Exception { }
public class MyClass
{
public MyClass()
{
throw new MyException();
}
}
public int ReturnFromDB(int input)
{
try
{
return repositorymethod(input);
}
catch(RepositoryException ex)
{
Throw new ParticularException("some message",ex);
}
}
The repositorymethod() uses a select query to return an integer data from db.
For a positive scenario, I can Assert the return value. But the code coverage is still 60 percent for this method in NCover.
How do I test the Catch part of this method? How do I trigger the Exception part? Even if I give a negative value as input, 0 is returned which doesn't trigger the Exception.
This is a good scenario for mocking. If your repository is a separate class with an interface, you can use swap out your real repository for a mock which explicitly throws the exception.
// Interface instead of concrete class
IRepository repository;
...
// Some way to inject a mock repo.
public void SetRepository(IRepository repo)
{
this.repository = repo;
}
public int ReturnFromDB(int input)
{
try
{
return repository.method(input);
}
catch(RepositoryException ex)
{
throw new ParticularException("some message",ex);
}
}
Then:
public class MockRepo : IRepository
{
public int method(int input)
{
throw new RepositoryException();
}
}
There are many ways to inject this mock into your class. If you are using Dependency Injection containers such as Spring or MEF, they can be configured to inject mocks for your tests. The setter method shown above is only for demonstration purposes.
I have the following method:
public void RegisterPlugin<T1>() where T1 : IWebrolePlugin
{
try
{
_container.RegisterType<T1>(new ContainerControlledLifetimeManager());
_container.RegisterType<IWebrolePlugin, T1>(typeof(T1).Name,new ContainerControlledLifetimeManager());
}catch(Exception e)
{
Trace.TraceError(e.ToString());
}
}
My problem is that when i do _container.Resolve() i get as expected the same instance of SomePlugin, but when using the following injection constructor it resolves new instances.
I have a the following registration also:
_container.RegisterType<WebsiteManager>(new InjectionConstructor(typeof(IDirectoryManager), typeof(IStore), typeof(IWebrolePlugin[])));
My problem is that the array of IWebrolePlugin[] is new instances. Can I do anything such my method
public T GetPlugin<T>() where T : IWebrolePlugin
{
return _container.Resolve<T>();
}
will return the same instances that the WebsiteManager got in its constructor?
When resolving, Unity first maps the interface to the concrete type by name and uses the concrete type and name as the BuildKey. This BuildKey is used for all aspects of constructing and injecting dependencies (including locating a lifetime manager). That is why the default registration (null name) and a named registration of the same type result in different instances being returned.
The easiest way to use the same instance is to align the registration names between the interface and the concrete type:
public void RegisterPlugin<T1>() where T1 : IWebrolePlugin
{
try
{
_container.RegisterType<T1>(typeof(T1).Name,
new ContainerControlledLifetimeManager());
_container.RegisterType<IWebrolePlugin, T1>(typeof(T1).Name);
}
catch (Exception e)
{
Trace.TraceError(e.ToString());
}
}
public T GetPlugin<T>() where T : IWebrolePlugin
{
return _container.Resolve<T>(typeof(T).Name);
}
This will result in same instance being returned for a straight Resolve and as part of a ResolveAll (for arrays).
we have 2 custom class (baseClass and ChildClass) the child class has inherited from the baseClass
when we get a exception on childClass, OnException event on the baseClass should be called
it'll be like MVC Controller OnException Events
We will use for logging.
In the general case it is not possible to do. The MVC OnException works because the framework catches any unhandled exceptions and forwards them to OnException. The framework code for calling a controller action is something like:
try
{
controller.SomeAction();
}
catch(Exception ex)
{
controller.OnException(ex);
}
The entire implementation depends on the caller of the code taking the responsibility to handle the exceptions. With a general calls that can be used by any code you can't make any assumptions on how the class will be called.
If we somehow can make all calls go through the base class we can make something similar:
public class Base
{
public BlahaMethod()
{
try
{
DoBlaha();
}
catch(Exception ex)
{
OnException(ex);
}
}
protected abstract void DoBlaha();
private void OnException(Exception ex)
{
// Handle exception
}
}
public class Derived
{
protected virtual void DoBlaha()
{
throw new NotImplementedException();
}
}
You can catch exception with a try-catch-finally construct. The only general exception handler (known to me) is the unhandled exception handler in the appdomain.
Long story short, I'm trying to use ELMAH with MVC 2 and Ninject, and I need to use parameterless constructors. I created an initial post about it here: Using a parameterless controller constructor with Ninject?
I was advised to use property injection instead of constructor injection. So I moved from this:
public class DepartmentsController : Controller
{
private IDepartmentsRepository departmentsRepository;
public DepartmentsController(IDepartmentsRepository departmentsRepository)
{
this.departmentsRepository = departmentsRepository;
}
...
}
to this:
public class DepartmentsController : Controller
{
private IDepartmentsRepository _departmentsRepository;
[Inject]
public IDepartmentsRepository DepartmentsRepository
{
get { return _departmentsRepository; }
set { _departmentsRepository = value; }
}
...
}
But in my other controller functions, whether I try to access DepartmentsRepository or _departmentsRepository, I get an object reference not set to an instance of an object error when I try to access it.
Is there something else I need to do here?
I had a similar problem. Have a look at my questions: Using Ninject with Membership.Provider.
Basically when you initialise DepartmentsController you need to injectthis (i.e. your departments controller into your Ninject kernal. So its something like:
public class DepartmentsController : Controller
{
private IDepartmentsRepository _departmentsRepository;
[Inject]
public IDepartmentsRepository DepartmentsRepository
{
get { return _departmentsRepository; }
set { _departmentsRepository = value; }
}
public DepartmentsController()
{
NinjectHelper.Kernel.Inject(this);
}
}
Where NinjectHelper in this case gets the current Ninject Kernel.
Try something like this:
Global.asax.cs
protected void Application_Start()
{
DependencyResolver.SetResolver(
new MyDependencyResolver(
new StandardKernel(
new MyModule())));
//...
}
MyDependencyResolver.cs
public class MyDependencyResolver : IDependencyResolver
{
private IKernel kernel;
public MyDependencyResolver(IKernel kernel)
{
this.kernel = kernel;
}
public object GetService(Type serviceType)
{
return kernel.TryGet(serviceType);
}
public IEnumerable<object> GetServices(Type serviceType)
{
return kernel.GetAll(serviceType);
}
}
MyModule.cs
public class MyModule : NinjectModule
{
public override void Load()
{
Bind<IDepartmentsRepository>().To<DepartmentsRepository>();
}
}
There could be 2 reasons for object reference not set exception.
1) Ninject does not know how to Bind IDepartmentsRepository to a concrete implementation of DepartmentsRepository ( I doubt that is the case though )
2) If you are trying to access DepartmentsRepository property in your controller's constructor, it will throw the exception (since Ninject is only able to inject Property Dependencies after the object is constructed).
Hope that helps.
As Daniel T. in the above comment posted, you should check out Ninject.Web.Mvc. If you use the NinjectHttpApplication in that project, it will autowire everything for you, so that when the NinjectControllerFactory constructs a new controller, it will call Inject() for you to fill the property injections.
An observation for anyone arriving here having problems "Using property injection instead of constructor injection" with Ninject even if not specifically with MVC Controllers.
Ninject will only identify the [Inject] attribute on a property and perform the property injection on classes that are being brought to life as part of a Ninject chain of DI.
If you are creating the object like this
var myObj = new MyObj();
Ninject doesn't know about the class instantiation and so won't know to perform any injection.
In the MVC world you can use
var emailer = DependencyResolver.Current.GetService<IEmailer>();