Not sure what to do here. invocationInfo.Proceed() always fails when trying to Intercept a factory that has constructor injection.
var container = new ServiceContainer();
container.Register<ICool,Cool>();
container.Register<ILogger, Logger>();
container.Register<IInterceptor, LoggingInterceptor>();
//Two problem lines
container.Register<int, IAwesome>((factory, value) => new Awesome(value, factory.GetInstance<ICool>()));
container.Intercept(sr => sr.ServiceType == typeof(IAwesome), sf => sf.GetInstance<IInterceptor>());
var awesome = container.GetInstance<int,IAwesome>(100);
awesome.Yo();
fails at this method in my interceptor.
public class LoggingInterceptor : IInterceptor
{
private ILogger _logger;
public LoggingInterceptor(ILogger logger)
{
_logger = logger;
}
public object Invoke(IInvocationInfo invocationInfo)
{
var returnValue = invocationInfo.Proceed(); //Exception here
return returnValue;
}
}
Exception:
An exception of type 'System.InvalidCastException' occurred in LightInject.dll but was not handled in user code
Additional information: Unable to cast object of type 'System.Func`1[ConsoleApplication1.IAwesome]' to type 'System.Object[]'.
Sorry I couldn't make a new tag for Lightinject. Not enough rep :/
I am the author of LightInject and it has been confirmed to be a bug when intercepting service instances that relies on runtime arguments such as the Awesome class.
The bug has been fixed and I will post back here as soon as a new NuGet package is available.
Best regards
Bernhard Richter
Related
I have a strange problem with the NET core dependency injection. When I'm trying to register a service, InsufficientExecutionStackException exception is thrown. What does this mean in this context? This is how I register the services (third line throws the exception):
var connectionStr = Configuration.GetValue<string>("databaseConnectionString");
services.AddSingleton<IDatabaseService>(s => new MySqlDatabaseService(connectionStr));
services.AddSingleton<IUserService>(s => new UserService(s.GetRequiredService<IUserRepository>(), secret, s.GetRequiredService<IAchievementService>()));//this line throws the exception
services.AddSingleton<IAchievementService, AchievementService>();
services.AddSingleton<IUserRepository, UserRepository>();
services.AddSingleton<IAchievementRepository, AchievementRepository>();
services.AddSingleton<IUserRequestService, UserRequestService>();
services.AddSingleton<AppSettingsService>();
Two services are injected in UserService class. These are the constructors of those:
public UserService(IUserRepository userRepository, string secret, IAchievementService achievementService)
{
this.achievementService = achievementService;
this.userRepository = userRepository;
this.secret = secret;
}
UserRepository:
public UserRepository(IDatabaseService databaseService)
{
this.databaseService = databaseService;
}
AchievementService:
public AchievementService(IAchievementRepository achievementRepository, IUserService userService)
{
this.achievementRepository = achievementRepository;
this.userService = userService;
this.userRequestService = userRequestService;
}
Another strange thing is that if I click "View details" from the Exception windows (I'm using Visual studio 2019) the debugger crashed and doesn't show anything.
It looks like you have a circular dependence between UserService and AchievementService. It's impossible for dotnet dependency injection to create an instance of the UserService without an instance of AchievementService. But to create an instance of AchievementService, you need an instance of UserService. So you're stuck in an infinite loop.
You should try to avoid this situation by removing the dependency. Do both services really need a dependency to the other one?
If it's not possible, you can try to use Lazy<Service> instead of just Service.
private readonly Lazy<IAchievementService> lazyAchievementService;
public UserService(Lazy<IAchievementService> lazyAchievementService, /*...*/)
{
this.lazyAchievementService = lazyAchievementService;
// ...
}
public void SomeFunction()
{
var achievementService = lazyAchievementService.Value;
achievementService.DoSomething();
}
This should allow you to create both class.
Given a class with a constructor signature of
public Foo(ILogger<Foo> logger) {
// ...
}
that I want to test, I need some way to provide an ILogger<Foo> in the test. It's been asked before, but the only answer then was to set up a full-blown service registry, configure logging and resolve the logger from there. This seems very overkill to me.
Is there a simple way to provide an implementation of ILogger<T> for testing purposes?
Note: it doesn't have to actually log anything - just not blow up when the subject under test tries to log something.
Starting from dotnet core 2.0 there's a generic NullLogger<T> class available:
var foo = new Foo(NullLogger<Foo>.Instance);
https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.logging.abstractions.nulllogger-1?view=aspnetcore-2.1 (docs)
https://github.com/aspnet/Logging/blob/master/src/Microsoft.Extensions.Logging.Abstractions/NullLoggerOfT.cs (source)
Or if you need it as part of your services:
services.AddSingleton<ILoggerFactory, NullLoggerFactory>();
https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.logging.abstractions.nullloggerfactory?view=aspnetcore-2.1 (docs)
You can create an instance of ILogger<Foo> using NullLoggerFactory as the factory.
Consider the following controller:
public abstract class Foo: Controller
{
public Foo(ILogger<Foo> logger) {
Logger = logger;
}
public ILogger Logger { get; private set; }
}
A sample unit test could be:
[TestMethod]
public void FooConstructorUnitTest()
{
// Arrange
ILogger<FooController> logger = new Logger<FooController>(new NullLoggerFactory());
// Act
FooController target = new FooController(logger);
// Assert
Assert.AreSame(logger, target.Logger);
}
If you use generic logger (ILogger<>) in your classes those instances are generated from IServiceProvider you should register generic NullLogger<> on service provider as below. Not important what you use generic type T in ILogger<>
services.AddSingleton(typeof(ILogger<>), typeof(NullLogger<>));
You have two options:
Create empty implementation of ILogger<Foo> by hand and pass an instance of it to ctor.
Create same empty implementation on the fly using some mocking framework like Moq, NSubstitute, etc.
You could inject ILoggerFactory instead and then create the logger
public Foo(ILoggerFactory loggerFactory) {
logger = loggerFactory.CreateLogger<Foo>();
// ...
}
At startup you need to add the NullLoggerFactory service of course:
services.AddSingleton<ILoggerFactory, NullLoggerFactory>()
From the docs for ILogger<T> (emphasis mine):
A generic interface for logging where the category name is derived from the specified TCategoryName type name. Generally used to enable activation of a named ILogger from dependency injection.
So one option would be to change the implementation of the Foo method to take a plain ILogger and use the NullLogger implementation.
You should use the Null Object Pattern. This has two advantages for you: 1) you can get your tests up and running quickly and they won't "blow up", and 2) anyone will be able to use your class without supplying a logger. Just use NullLogger.Instance, or NullLoggerFactory.Instance.
However, you should use a mocking framework to verify that log calls get made. Here is some sample code with Moq.
[TestMethod]
public void TestLogError()
{
var recordId = new Guid("0b88ae00-7889-414a-aa26-18f206470001");
_logTest.ProcessWithException(recordId);
_loggerMock.Verify
(
l => l.Log
(
//Check the severity level
LogLevel.Error,
//This may or may not be relevant to your scenario
It.IsAny<EventId>(),
//This is the magical Moq code that exposes internal log processing from the extension methods
It.Is<It.IsAnyType>((state, t) =>
//This confirms that the correct log message was sent to the logger. {OriginalFormat} should match the value passed to the logger
//Note: messages should be retrieved from a service that will probably store the strings in a resource file
CheckValue(state, LogTest.ErrorMessage, "{OriginalFormat}") &&
//This confirms that an argument with a key of "recordId" was sent with the correct value
//In Application Insights, this will turn up in Custom Dimensions
CheckValue(state, recordId, nameof(recordId))
),
//Confirm the exception type
It.IsAny<NotImplementedException>(),
//Accept any valid Func here. The Func is specified by the extension methods
(Func<It.IsAnyType, Exception, string>)It.IsAny<object>()),
//Make sure the message was logged the correct number of times
Times.Exactly(1)
);
}
private static bool CheckValue(object state, object expectedValue, string key)
{
var keyValuePairList = (IReadOnlyList<KeyValuePair<string, object>>)state;
var actualValue = keyValuePairList.First(kvp => string.Compare(kvp.Key, key, StringComparison.Ordinal) == 0).Value;
return expectedValue.Equals(actualValue);
}
For more context, see this article.
If you need to verify the calls in addition to just provide the instance, it gets somewhat complicated. The reason is that most calls does not actually belong to the ILogger interface itself.
I have written a more detailed answer here.
Here is a small overview.
Example of a method that I have made to work with NSubstitute:
public static class LoggerTestingExtensions
{
public static void LogError(this ILogger logger, string message)
{
logger.Log(
LogLevel.Error,
0,
Arg.Is<FormattedLogValues>(v => v.ToString() == message),
Arg.Any<Exception>(),
Arg.Any<Func<object, Exception, string>>());
}
}
And this is how it can be used:
_logger.Received(1).LogError("Something bad happened");
You should try this for mocking ILogger:
mock.Setup(m => m.Log<object>(It.IsAny<LogLevel>(),It.IsAny<EventId>(),It.IsAny<object>(),It.IsAny<Exception>(),It.IsAny<Func<object, Exception,string>>()))
.Callback<LogLevel, EventId, object, Exception, Func<object, Exception, string>>((logLevel, eventId, obj, exception, func) =>
{
string msg = func.Invoke(obj, exception);
Console.WriteLine(msg);
});
This worked for me:
private FooController _fooController;
private Mock<ILogger<FooController>> _logger;
[TestInitialize]
public void Setup()
{
_logger = new Mock<ILogger<FooController>>();
_fooController = new FooController(_logger.Object);
}
I have followed this tutorial which has worked great, until I modified my DbContext to have an additional constructor. I am now having issues with the resolution and not sure what to do to fix this. Is there an easy way to force it to grab the parameterless constructor or I am approaching this incorrectly?
DbContext with two constructors:
public class DashboardDbContext : DbContext
{
public DashboardDbContext() : base("DefaultConnection") { }
public DashboardDbContext(DbConnection dbConnection, bool owns)
: base(dbConnection, owns) { }
}
SiteController constructor:
private readonly IDashboardRepository _repo;
public SiteController(IDashboardRepository repo)
{
_repo = repo;
}
Repository:
DashboardDbContext _context;
public DashboardRepository(DashboardDbContext context)
{
_context = context;
}
UnityResolver code:
public class UnityResolver : IDependencyResolver
{
private readonly IUnityContainer _container;
public UnityResolver(IUnityContainer container)
{
_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();
}
}
WebApiConfig:
var container = new UnityContainer();
container.RegisterType<IDashboardRepository, DashboardRepository>(new HierarchicalLifetimeManager());
config.DependencyResolver = new UnityResolver(container);
Error from WebApi Call:
System.InvalidOperationException: An error occurred when trying to create a controller of type 'SiteController'. Make sure that the controller has a parameterless public constructor.
at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)
at System.Web.Http.Controllers.HttpControllerDescriptor.CreateController(HttpRequestMessage request)
at System.Web.Http.Dispatcher.HttpControllerDispatcher.SendAsyncCore(HttpRequestMessage request, CancellationToken cancellationToken)
at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__0.MoveNext()
InnerException: System.ArgumentException: Type 'Dashboard.Web.Controllers.SiteController' does not have a default constructor.
at System.Linq.Expressions.Expression.New(Type type)
at System.Web.Http.Internal.TypeActivator.Create[TBase](Type instanceType)
at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.GetInstanceOrActivator(HttpRequestMessage request, Type controllerType, Func`1& activator)
at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)
The tutorial was great and has been working well for me up until I added the second constructor.
What's happening is that you're bitten by this problem. Basically, what happened is that you didn't register your controllers explicitly in your container. Unity tries to resolve unregistered concrete types for you, but because it can't resolve it (caused by an error in your configuration), it return null. It is forced to return null, because Web API forces it to do so due to the IDependencyResolver contract. Since Unity returns null, Web API will try to create the controller itself, but since it doesn't have a default constructor it will throw the "Make sure that the controller has a parameterless public constructor" exception. This exception message is misleading and doesn't explain the real cause.
You would have seen a much clearer exception message if you registered your controllers explicitly, and that's why you should always register all root types explicitly.
But of course, the configuration error comes from you adding the second constructor to your DbContext. Unity always tries to pick the constructor with the most arguments, but it has no idea how to resolve this particular constructor.
So the real cause is that you are trying to use Unity's auto-wiring capabilities to create the DbContext. DbContext is a special type that shouldn't be auto-wired. It is a framework type and you should therefore fallback to registering it using a factory delegate:
container.Register<DashboardDbContext>(
new InjectionFactory(c => new DashboardDbContext()));
In my case, it was because of exception inside the constructor of my injected dependency (in your example - inside DashboardRepository constructor). The exception was caught somewhere inside MVC infrastructure. I found this after I added logs in relevant places.
I had the same issue and I resolved it by making changes in the UnityConfig.cs file In order to resolve the dependency issue in the UnityConfig.cs file you have to add:
public static void RegisterComponents()
{
var container = new UnityContainer();
container.RegisterType<ITestService, TestService>();
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}
I had the same problem. I googled it for two days. At last I accidentally noticed that the problem was access modifier of the constructor of the Controller.
I didn’t put the public key word behind the Controller’s constructor.
public class MyController : ApiController
{
private readonly IMyClass _myClass;
public MyController(IMyClass myClass)
{
_myClass = myClass;
}
}
I add this experience as another answer maybe someone else made a similar mistake.
Sometimes because you are resolving your interface in ContainerBootstraper.cs it's very difficult to catch the error. In my case there was an error in resolving the implementation of the interface I've injected to the api controller. I couldn't find the error because I have resolve the interface in my bootstraperContainer like this:
container.RegisterType<IInterfaceApi, MyInterfaceImplementaionHelper>(new ContainerControlledLifetimeManager());
then I've adde the following line in my bootstrap container : container.RegisterType<MyController>();
so when I compile the project , compiler complained and stopped in above line and showed the error.
If you are using UnityConfig.cs to resister your type's mappings like below.
public static void RegisterTypes(IUnityContainer container)
{
container.RegisterType<IProductRepository, ProductRepository>();
}
You have to let the know **webApiConfig.cs** about Container
config.DependencyResolver = new Unity.AspNet.WebApi.UnityDependencyResolver(UnityConfig.Container);
I really, really hope this answer helps someone else from wasting a day and a half of messing around with; Ninject, MVC design pattern, Global.asax, Web Common files etc etc.
The error itself was completely misleading in my case.
My entire application was working sound with the exception of when I called one particualr controller lets call TestController.
Test controller was using Ninject to inject an interface lets call ITest like so -
public class TestController : ApiController
{
private readonly ITest _test;
public TestController (ITest test)
{
_test= test;
}
I was making a simple GET request to one of the methods in TestController and was getting the aforementioned error for this threads question.
I eventually boiled it down to the error only occuring when ITest was injected as a parameter (as I tested a different interface and it worked soundly!)
This led me to check the Test class and realsied that I had injected an instance of itself into it! Like so -
public class Test: ITest
{
private readonly ITest_test;
public Test(ITest test)
{
_test = test;
}
Thus resulting in the entire call falling over as an unhandled exception and returning a completely bizarre error that didn't help me at all!
If you have an interface in your controller
public myController(IXInterface Xinstance){}
You must register them to Dependency Injection container.
container.Bind<IXInterface>().To<XClass>().InRequestScope();
I've got this error when I accidentally defined a property as a specific object type, instead of the interface type I have defined in UnityContainer.
For example:
Defining UnityContainer:
var container = new UnityContainer();
container.RegisterInstance(typeof(IDashboardRepository), DashboardRepository);
config.DependencyResolver = new UnityResolver(container);
SiteController (the wrong way - notice repo type):
private readonly DashboardRepository _repo;
public SiteController(DashboardRepository repo)
{
_repo = repo;
}
SiteController (the right way):
private readonly IDashboardRepository _repo;
public SiteController(IDashboardRepository repo)
{
_repo = repo;
}
In my case, Unity turned out to be a red herring. My problem was a result of different projects targeting different versions of .NET. Unity was set up right and everything was registered with the container correctly. Everything compiled fine. But the type was in a class library, and the class library was set to target .NET Framework 4.0. The WebApi project using Unity was set to target .NET Framework 4.5. Changing the class library to also target 4.5 fixed the problem for me.
I discovered this by commenting out the DI constructor and adding default constructor. I commented out the controller methods and had them throw NotImplementedException. I confirmed that I could reach the controller, and seeing my NotImplementedException told me it was instantiating the controller fine. Next, in the default constructor, I manually instantiated the dependency chain instead of relying on Unity. It still compiled, but when I ran it the error message came back. This confirmed for me that I still got the error even when Unity was out of the picture. Finally, I started at the bottom of the chain and worked my way up, commenting out one line at a time and retesting until I no longer got the error message. This pointed me in the direction of the offending class, and from there I figured out that it was isolated to a single assembly.
Install Nuget Package Unit.WebAP instead of Unity.MVC5 Make sure the correct unity package is installed using nuget
I Installed Unity.MVC5 and was facing similar exception "parameterless constructor"
public static void RegisterComponents()
{
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<ICar, Tesla>();
GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);
}
I am using servicestack and having problems with auto wiring.
Error trying to resolve Service '{Service}' or one of its autowired dependencies (see inner exception for details)
I don't need help figuring how exactly what the problem is. What I actually want is a way to see the inner exception. The inner exception should tell me the except problem without me having to figure it out but it not displayed in either the exception returned, or in the logs.
Setting DebugMode doesn't help either, it just includes the stack track of the topmost exception.
So basically, how do I stop servicestack from hiding the inner exception details?
I ran into this same issue and it ended up being that there was an exception being thrown inside of the constructor that I had created for the particular endpoint class. Example...
public class PartnerService : Service
{
private PartnerManagementService _partnerManagementService;
public PartnerService()
{
var configuration = new Configuration();
_partnerManagementService = new PartnerManagementService(configuration);
}
public object Get(PartnerGet partner)
{
try
{
var partners = _partnerManagementService.getPartners();
if (!partners.Any())
{
return new HttpError(HttpStatusCode.NotFound, "Partners Could not be found");
}
return partners;
}
catch (Exception e)
{
return new HttpError(HttpStatusCode.InternalServerError, e);
}
}
If it so happens that an exception is thrown inside of the constructor, ServiceStack will not be able to resolve the service or one of its dependencies, in this case that dependency being the constructor for the class.
If you put a try/catch in the constructor for the class you could get an exception that actually makes sense.
ServiceStack should already return the inner Exception, i.e. here's the source of the error:
private Exception CreateResolveException<TService>(Exception ex)
{
var errMsg = "Error trying to resolve Service '{0}' or one of its autowired dependencies (see inner exception for details).".Fmt(typeof(TService).FullName);
return new Exception(errMsg, ex);
}
Basically there was a problem with your IOC configuration and that one of the dependencies caused an error.
You can change ServiceStack to serialize the Inner Exception with:
SetConfig(new EndpointHostConfig {
ReturnsInnerException = true,
});
But this already defaults to true.
So the exception should already contain the Inner Exception, are you referring to what Exception gets serialized or the exception thrown in code?
One option could be to grab the actual source code from Github and add it as a project to your solution, as opposed to using a compiled DLL, then you could step through the actual code and see exactly where the exception is raised and why.
I have exactly the same exception.
In my case, it happens once migrated to ServiceStack v4. With v3, all works perfectly.
IoC configuration
public class AppHost : AppHostBase
{
public AppHost() : base("Northwind web services", typeof(CustomersService).Assembly)
{ }
public override void Configure( Container container )
{
SetConfig(new HostConfig
{
DebugMode = true,
ReturnsInnerException = true,
});
var dbFactory = new OrmLiteConnectionFactory("~/Northwind.sqlite".MapHostAbsolutePath(), SqliteDialect.Provider);
container.Register(dbFactory);
// Dependencies
container.RegisterAs<CustomerEntityRepository, ICustomerEntityRepository>();
container.RegisterAutoWired<CustomersService>();
}
}
Base class
public abstract class Repository<TEntity> : IRepository<TEntity> where TEntity : IEntity, new()
{
protected IDbConnectionFactory dbFactory { get; set; }
public Repository( IDbConnectionFactory factory )
{
dbFactory = factory;
}
}
Inherited class
public class CustomerEntityRepository : Repository<CustomerEntity>, ICustomerEntityRepository
{
public CustomerEntityRepository( IDbConnectionFactory dbFactory )
: base(dbFactory)
{
}
}
}
Only solution I've found is:
container.RegisterAs<ICustomerEntityRepository>(c => new CustomerEntityRepository(dbFactury));
Here's full exception message returned http://pastebin.com/jJntNN5p
When I install StructureMap for my project and use:
public class IndexController : Controller
{
private readonly IMapper<UserModel, UserDto> _mapper;
public IndexController(IMapper<UserModel, UserDto> mapper)
{
_mapper = mapper;
}
public ActionResult Index()
{
List<UserDto> userDb = UserDb.GetAll();
UserModel userModel = _mapper.Map(userDb[0]);
return View();
}
}
After run with an server error message:
No parameterless constructor defined for this object. Description: An
unhandled exception occurred during the execution of the current web
request. Please review the stack trace for more information about the
error and where it originated in the code.
Exception Details: System.MissingMethodException: No parameterless constructor defined for this object.
...
But I don't know much about the principle of dependency inversion. Please help me to resolve this.
This is ObjectFactory :
public static class IoC {
public static IContainer Initialize() {
ObjectFactory.Initialize(x =>
{
x.Scan(scan =>
{
scan.TheCallingAssembly();
scan.WithDefaultConventions();
});
// x.For<IExample>().Use<Example>();
});
return ObjectFactory.Container;
}
}
What do I need to do next?
You need to tell StructureMap how to wire up all types that don't follow the default convention (which you use in your scan). The default convention is to wire up all interfaces to concrete implementations with the same name as the interface (minus the "I" prefix).
In your case you need to tell StructureMap to wire up all needed closed generic types of IMapper using:
x.For(typeof(IMapper<,>)).Use(typeof(MyConcreteMapper<,>);
Put the line above where you currently have the x.For<IExample>().Use<Example().