I am having problem with construction injection fail.
When I call Restful API, the service return the message "An error occurred when trying to create a controller of type 'TasksController'. Make sure that the controller has a parameterless public constructor."
The cause of this issue is the Web API Controller can't construct the class because of wrong parameter in the constructor.
This is Ninject Configuration
container.Bind<IAddTaskQueryProcessor>().To<AddTaskQueryProcessor>().InRequestScope();
container.Bind<ITaskByIdQueryProcessor>().To<TaskByIdQueryProcessor>().InRequestScope();
container.Bind<IPagedDataRequestFactory>().To<PagedDataRequestFactory>().InSingletonScope();
container.Bind<IAllTasksInquiryProcessor>().To<AllTasksInquiryProcessor>().InRequestScope();
This is a constructor of a class of a Controller. the parameters are injected when calling the constructor.
public TasksController(IAddTaskMaintenanceProcessor addTaskMaintenanceProcessor, ITaskByIdInquiryProcessor taskByIdInquiryProcessor,
IUpdateTaskMaintenanceProcessor updateTaskMaintenanceProcessor,
IPagedDataRequestFactory pagedDataRequestFactory,
IAllTasksInquiryProcessor allTasksInquiryProcessor)
{
_addTaskMaintenanceProcessor = addTaskMaintenanceProcessor;
_taskByIdInquiryProcessor = taskByIdInquiryProcessor;
_updateTaskMaintenanceProcessor = updateTaskMaintenanceProcessor;
_pagedDataRequestFactory = pagedDataRequestFactory;
_allTasksInquiryProcessor = allTasksInquiryProcessor;
}
[Environment]
ASP.NET Web API 2.1
NInject 3.2.2
How to check which parameter in a constructor is wrong?
I solved this problem. the parameters in the constructor are injected correctly. but a parameter IAllTaskQueryProcess in AllTaskInqueryProcess's constructor is not injected. so that ASP.NET engine can't invoke the controller class
public AllTasksInquiryProcessor(IAllTasksQueryProcessor queryProcessor, IAutoMapper autoMapper)
{
_queryProcessor = queryProcessor;
_autoMapper = autoMapper;
}
Related
I've done the Plugins.Add(new AutoQueryFeature { MaxLimit = 100 }); and used it in startup Configure Method.
This is dto inherites QueryDb
I keep encountering AutoQuery is null and NullReferenceException thrown at AutoQuery.CreateQuery() Method. And CallStacks can not show ExternalCodes. I have no ideas where it gone wrong by referring to TechStacks Project.
The project references ServiceStack.Core 5.7.0
I'm able to get AutoQuery by using the below code.
var autoquery = TryResolve<IAutoQueryDb>()
None of your code samples show the 3 important things required for AutoQuery, the AutoQueryFeature plugin registration in your AppHost’s Configure(), the definition of your Service class that implements the Service base class, the public IAutoQueryDb AutoQuery { get; set; } public property.
If they’re configured correctly the IAutoQueryDb dependency should be injected.
I have a WebAPI service using SimpleInjector. I have this set up using AsyncScopedLifestyle for my scoped dependencies, and one of these dependencies is my Entity Framework DataContext. Many things in my service depend on the DataContext, and it is generally injected in to my MediatR handlers using constructor injection - this works well. Separately I have a few areas where I need to create an instance of an object given its type (as a string), so I have created a custom activator class (ResolvingActivator) that is configured with a reference to Container.GetInstance(Type):
In my container bootstrap code:
ResolvingActivator.Configure(container.GetInstance);
I can then create objects by using methods such as:
ResolvingActivator.CreateInstance<T>(typeName)
When I'm using WebAPI, the above is working perfectly.
A further part of the project is a legacy API that uses WCF. I have implemented this as a translation layer, where I translate old message formats to new message formats and then dispatch the messages to the Mediator; I then translate the responses (in new format) back to old format and return those to the caller. Because I need access to the Mediator in my WCF services, I'm injecting this in their constructors, and using the SimpleInjector.Integration.Wcf package to let SimpleInjector's supplied SimpleInjectorServiceHostFactory build instances of the services. I've also created a hybrid lifestyle, so I can use the same container for my both my WebAPI and WCF services:
container.Options.DefaultScopedLifestyle = Lifestyle.CreateHybrid(
new AsyncScopedLifestyle(),
new WcfOperationLifestyle());
This works well for some calls, but when a call ultimately calls my ResolvingActivator class, I get an ActivationException thrown, with the following message:
The DataContext is registered as 'Hybrid Async Scoped / WCF Operation' lifestyle, but the instance is requested outside the context of an active (Hybrid Async Scoped / WCF Operation) scope.
As I only receive this error when making WCF calls, I'm wondering if I have something wrong in my configuration. In a nutshell, this will work:
public class SomeClass
{
private readonly DataContext db;
public SomeClass(DataContext db)
{
this.db = db;
}
public bool SomeMethod() => this.db.Table.Any();
}
But this will not:
public class SomeClass
{
public bool SomeMethod()
{
// Code behind is calling container.GetInstance(typeof(DataContext))
var db = ResolvingActivator.CreateInstance<DataContext>();
return db.Table.Any();
}
}
Any ideas where I'm going wrong?
Edit: here is the stack trace from the ActivationException:
at SimpleInjector.Scope.GetScopelessInstance[TImplementation](ScopedRegistration`1 registration)
at SimpleInjector.Scope.GetInstance[TImplementation](ScopedRegistration`1 registration, Scope scope)
at SimpleInjector.Advanced.Internal.LazyScopedRegistration`1.GetInstance(Scope scope)
at lambda_method(Closure )
at SimpleInjector.InstanceProducer.GetInstance()
at SimpleInjector.Container.GetInstance(Type serviceType)
at Service.Core.ResolvingActivator.CreateInstance(Type type) in Service.Core\ResolvingActivator.cs:line 43
at Service.Core.ResolvingActivator.CreateInstance(String typeName) in Service.Core\ResolvingActivator.cs:line 35
at Service.Core.ResolvingActivator.CreateInstance[TService](String typeName) in Service.Core\ResolvingActivator.cs:line 69
With a full stack trace here: https://pastebin.com/0WkyHGKv
After close inspection of the stack trace, I can conclude what's going on: async.
The WcfOperationLifestyle under the covers depends on WCF's OperationContext.Current property, but this property has a thread-affinity and doesn't flow with async operations. This is something that has to be fixed in the integration library for Simple Injector; it simply doesn't support async at the moment.
Instead, wrap a decorator around your handlers that start and end a new async scope. This prevents you from having to use the WcfOperationLifestyle all together. Take a look at the ThreadScopedCommandHandlerProxy<T> implementation here to get an idea how to do this (but use AsyncScopedLifestyle instead).
I have create a web api controller, I have repository pattern so i used Ninject. In constructor i creating Object for interface. Its working fine when i am using it in Normal Controller class. But when i create same in api controller constructor it not working.
Code:
//Its not working
IAdminRepository mAdminRepository;
public AccountApiController(IAdminRepository pAdminRepository)
{
mAdminRepository = pAdminRepository;
}
[HttpPost]
[ActionName("ValidateLogin")]
public LoginResponse ValidateLogin([FromBody] LoginInfo login)
{
// some code hare
}
//But its working
private AccountApiController()
{
}
Its working as its have no parameter in constructor. Once again telling u that i have used same parameterized constructor in Normal controller classes in same project that's working.
I am trying make use of Mehdi El Gueddari's DBContextScope solution and DI it into my WebAPI2 Controller as follows:
NinjectConfigurator.cs:
container.Bind<IUserProfileInquiryProcessor>().To<UserProfileInquiryProcessor>().InRequestScope();
container.Bind<IDbContextScopeFactory>().To<DbContextScopeFactory>().InSingletonScope();
UserProfileController.cs:
public UserProfileController(
IUserProfileInquiryProcessor userProfileInquiryProcessor,
IDbContextScopeFactory dbContextScopeFactory)
{
_dbContextScopeFactory = dbContextScopeFactory;
_userProfileInquiryProcessor = userProfileInquiryProcessor;
}
However, Ninject appears to be failing to inject IDbContextScopeFactory and returns with the following exception:
An error occurred when trying to create a controller of type 'UserProfileController'. Make sure that the controller has a parameterless public constructor.
I know it is IDbContextScopeFactory that is failing to resolve and the controller is created if I omit that parameter (only) from the constructor.
Can anyone advise what I am doing wrong or what I should try? Thanks.
I am using the Ninject Factory Extensions so that I can create objects that have services injected plus custom values
so:
public interface IGameOperationsFactory
{
ISpinEvaluator Create(GameArtifact game);
IReelSpinner CreateSpinner(GameArtifact game);
}
Then in module:
Bind<IGameOperationsFactory>().ToFactory().InSingletonScope();
Bind<ISpinEvaluator>().To<DefaultSpinEvaluatorImpl>();
Bind<IReelSpinner>().To<DefaultReelSpinnerImpl>();
The actual factory gets injected in a classes' constructor and is then used like:
_spinner = _factory.CreateSpinner(_artifact);
_spinEval = _factory.Create(_artifact);
Where _artifact is of type GameArtifact
Then in each of the implementation's constructors services plus the passed in objects are injected. The GameArtifact is successfully passed in the first constructor, and in the second one a "new" GameArtifact is passed in, i.e. not a null one but one with just default values as if the framework just called
new GameArtifact()
instead of passing in the already existing one!
The Constructor for the two objects is very similar, but the one that doesn't work looks like:
[Inject]
public DefaultReelSpinnerImpl(GameArtifact ga, IGameOperationsFactory factory, IRandomService serv)
{
_rand = serv;
_ra = ga.Reels;
_mainReels = factory.Create(_ra);
_winLine = ga.Config.WinLine;
}
Where the factory and serv are injected by Ninject and ga is SUPPOSED to be passed in via the factory.
Anyone have a clue why a new "fresh" object is passed in rather than the one I passed in??
I have rewritten you sample a little bit, and it seems to work fine. Could you provide more detailed code sample?
My implementation
I have changed verb Create to Get to match Ninject conventions
public interface IGameOperationsFactory
{
ISpinEvaluator GetSpinEvaluator(GameArtifact gameArtifact);
IReelSpinner GetReelSpinner(GameArtifact gameArtifact);
}
Ninject configuration
I have added named bindings to configure factory
Bind<ISpinEvaluator>()
.To<DefaultSpinEvaluatorImpl>()
.Named("SpinEvaluator");
Bind<IReelSpinner>()
.To<DefaultReelSpinnerImpl>()
.Named("ReelSpinner");
Bind<IGameOperationsFactory>()
.ToFactory();
ps: full sample with tests