ServiceStack: container.AutoWire(this) gives a NullReferenceException - dependency-injection

If I in my AppHostBase descendant (web api project ) use container.AutoWire(this), it will result in a NullReferenceException in the ServiceStack code, if I am using a web project, thus starting it with the CreateHostBuilder(args).Build().Run(); in the main method.
The error is reproduced in this Github project: https://github.com/tedekeroth/ServiceStackAutoWireTest
The error occurs in AppHostBase.Netcore.Cs, line 158:
If I remove the container.AutoWire(this); in TestAppHost.cs, the error goes away, but then the dependency injection does not work, meaning the Logger in TestAppHostproperty is not assigned:
I am not sure why this happens or what I can do about it. I'd appreciate some input, thanks.
Setup
Visual Studio 2019
Target framework: .NET 5.0 (Console Application)
Project SDK: Microsoft.NET.Sdk.Web
ServiceStack 5.11.0

The IOC AutoWire API attempts to autowire all public property dependencies of an object which is definitely something you should never attempt to do with the AppHost which encapsulates the configuration and behavior of your ServiceStack App where indiscriminatingly overriding every public property is going to leave it in a corrupted state.
Registering your AppHost in the IOC shouldn't be necessary as it's available everywhere via the HostContext.AppHost singleton. It's also a bad idea trying to reference any type defined in your Host Project, (the AppHost being the canonical example) since it creates a circular reference to your Host project in your App logic dependencies which shouldn't have any references back to its Host project, your Host project is supposed to reference all your projects .dll's, configure your App's and all its dependencies, not the other way around.
Should you need access to any Plugins it's recommended to use the GetPlugin<T>() API in your Service for optional plugins or AssertPlugin<T>() for required plugins. If you need to resolve any deps manually you can use TryResolve<T>() API in your Service class. For any of your App's custom config I'd recommend registering them in a custom AppConfig class for your Services to access like any other dependencies.
Otherwise if you really need access to the AppHost you can use the HostContext.AppHost singleton. If you absolutely need to have the AppHost in the IOC, just register it as a normal singleton, i.e. don't try to autowire it:
container.Register<IAppHost>(c => this);
However as mentioned earlier I'd strongly advise against it, have everything your App needs in a custom class (e.g. AppConfig) that is accessed like a normal dependency.

Related

Accessing NInject kernel from a dependent assembly

I have an ASP.NET MVC 5 project where I need to use a custom web-service based e-mail service (long story! Can't change it, though).
I wrapped up the e-mail web service into a separate assembly and packaged all the dependencies in there.
In my ASP.NET MVC 5 app, I'm using Ninject for dependency injection, and it works really well inside the MVC project - the controllers get their dependencies injected "magically" , and it's a joy to use.
But now: for my e-mail sending component, I'd like to write a "mock" or simulator for use locally when doing development. So basically, I would need to be able to bind the IMailService to both the MailService (real implementation), as well as the MailServiceSimulator (my dummy implementation). Ninject supports that, no problem:
Bind<IMailService>().To<MailService>().Named("Production");
Bind<IMailService>().To<MailServiceSimulator>().Named("Simulator");
BUT: the problem is this: I register all the dependencies with Ninject in the MVC application (in the NinjectWebCommon class in App_Startup) - but I'd like to be able to have a factory class in my "mail service" project that can be told to return a real implementation - or the simulator - for the mail sending component. But how can I get access to the Ninject kernel in order to get the desired service?
Somehow, I'd need to be able to do either
return kernel.Get<IMailService>("Production");
if the real implementation is desired, or
return kernel.Get<IMailService>("Simulator");
if the development-time simulator for the IMailService should be used.
Since my MVC app already uses the "MailService" assembly as a reference, I cannot really make the "MailService" use the "MVC" project as a reference.... so how can I access the Ninject kernel (that gets created inside the "MVC" assembly at startup) from within a referenced "MailService" assembly?? Seems I'm going in circles, one assembly requiring the other and then the other requiring the first one again as a dependency.....
Any ideas?
Accessing the Kernel, or doing DI business, in your MailService project seems like a leaky abstraction.
Assuming the "Production/Simulator" switch is located in the appSettings as a "MailSwitch" setting, you may leave out the named bindings and go for :
Bind<IMailService>().To<MailService>()
.When(r => ConfigurationManager.AppSettings.Get("MailSwitch")=="Production");
Bind<IMailService>().To<MailServiceSimulator>()
.When(r => ConfigurationManager.AppSettings.Get("MailSwitch")=="Simulator");

How to inject 3rd party IOC container into ASP.NET Core Startup class

I'm creating a web API using ASP.NET Core, and I'm using SimpleInjector as my DI framework. I understand the basics of how to use SI with ASP.NET Core; my problem is more an architectural one.
I have a project with integration tests for the API project, in order to test the raw API endpoints and responses. Naturally, the test server (set up using Microsoft.AspNetCore.TestHost) should use the API project's real Startup class.
The problem lies in where to register mocks for the controllers' dependencies, because I don't want to have all the production implementations being registered when testing: Firstly, most of them are, of course, dependencies used by the production implementations of the controller dependencies I'll be mocking in the first place; and secondly, in case I update my controllers and forget to register mocks of the new dependencies, I want my code to fail (container verification) instead of silently using production dependencies that are present in the container.
Thus, the dependencies can't be registered in the Startup class. That's fine by me – I think I'd rather keep the composition root in a separate assembly referencing all other assemblies, anyway. AFAICS the ASP.NET Core project would need to reference this project, which exposes a single method that returns a pre-registered container that can be used in the Startup class, where it's needed to register e.g. the controller activator (and will undergo final validation).
But this begs the question: How to get the container – being already registered with all my application components (whether production implementations from the composition root project, or mocks from the integration test project) – into my Startup class?
My initial solution is to simply have a static property on the Startup class called e.g. Container, and assign that before using WebHostBuilder. This seems "pragmatically robust": The application will fail fast (NullReferenceException) if it's not set before the Startup class is run, and the property is only used during setup, so I don't really need to guard against it being set multiple times or being set to null or any such thing – if it's assigned before startup, it works, if not, it won't start.
Does this seem like a solid solution, or am I oblivious to any obvious ways this will will come back to bite me later on? Are there any better solutions?

How to resolve Dependency within Dependency

I have 4 Projects in a solution
DAL_Project
BLL_Project
Interface_Project
WebApi_Project
Interface_Project has two interfaces ICar_DAL and ICar_BLL
DAL_Project has a class Car_DAL that implements ICar_DAL
BLL_Project has a class Car_BLL that implements ICar_BLL and its constructor takes in ICar_DAL
WebApi_Project has an api controller CarApiController and its constructor takes in ICar_BLL
the dependency resolution of WebApi Controller's constructor is done by Unity.WebApi using this in Bootstrapper.cs:
container.RegisterType<ICar_BLL, Car_BLL>();
this would have worked if my Car_BLL further didn't require ICar_DAL in its constructor.
to make it work i can do some thing like this:
container.RegisterType<ICar_BLL, Car_BLL>();
container.RegisterType<ICar_DAL, Car_DAL>();
but that would mean that i need to add reference to DAL_Project in my WebApi_Project which is something i would never want to do. DAL_Project should only be referred by BLL_Project
How can i solve this issue?
but that would mean that i need to add reference to DAL_Project in my
WebApi_Project which is something i would never want to do.
Oh you seem to have some misunderstanding about how Dependency should be done if you don't want to do that. The DI container is configured in the outermost layer of your application which is actually the host. It is also referred to as the Composition Root. In your case this is the hosting application of your Web API. If you are using ASP.NET to host your Web API then this is the right place to do the composition root and reference all the other underlying projects.
Personally in complex project I tend to have a ProjectName.Composition class library which serves me as a Composition root. this is where I configure my DI container and this is the project that references all the others - coz obviously in order to configure your DI root you need all the dependent projects and implementations. This .Composition assembly is then references in the hosting application and the Bootstrapper.Initialize method called in the Initialize method of the hosting application.
In the case of ASP.NET host that would be Application_Start in Global.asax
In case of a desktop application or a self-host that would be the Main method which is the entry point.

ASP.Net Web API DependencyResolver - Framework trying to resolve numerous internal dependencies that I don't care about?

My small Web API project (hosted via SelfHostHttpServer) has a few dependencies I want to inject into the controllers. In order to do this, I have implemented IDependencyResolver and called httpConfig.ServiceResolver.SetResolver.
This would work fine, except it seems I need to satisfy the internal dependencies the Web API requires. The first time I ran it, I saw that it needed to resolve the controller factory, so I added an instance of DefaultHttpControllerFactory to my container. Now every damn time I refresh the page, it crashes with the next unresolved dependency the framework is trying to resolve.
Am I going about this the wrong way, or am I really supposed to try and guess all of the default implementations and be forced through this crash-fix-refresh cycle of discovering what dependencies are required for the Web API framework to work correctly?
What your resolver is doing in case it can't resolve the dependency? The proper behaviour should be returning null. ASP.NET Web API DependencyResolver (httpConfig.ServiceResolver) is internally using two resolvers:
The one you set through SetResolver (user rosolver)
The built in DefaultServiceResolver
If user resolver returns null for dependency then Web API falls back to DefaultServiceResolver which can handle all built-in dependencies.

How To Properly Configure Ninject.Extensions.Logging.Log4Net in my MVC3 project

I am trying to properly use Ninject to inject log4net logging into my MVC3 application. I am using the Ninject.MVC3 package, so I have the NinjectMVC3 class that automatically extends the App_Start method and contains the RegisterServices method that binds all dependencies. I also have the Ninject.Extensions.Logging.Log4Net package, but I don't know how to use it. I already know how to configure log4net in my web.config, but don't know how to use this extension for DI.
I have read all the following articles/posts, but none of them seem to define how to properly setup a project for DI logging.
At http://dotnetdarren.wordpress.com/2010/07/29/logging-in-mvc-part-4-log4net/, Darren
provides a great article, but doesn't seem to deal with DI (at least I don't see it).
At Using Ninject to fill Log4Net Dependency,
Remo Gloor states here that the extensions should provide all that's needed for implementation, but it doesn't show the code of how to instantiate it.
The documentation for ninject.extensions.logging at https://github.com/ninject/ninject.extensions.logging/wiki/Using is very limited at best. I have re-read it many times, and still don't see how to use bind the injection in the NinjectMVC3 class, or concrete examples of how to call the logger from my controller class for example.
At the most promising article, Moosaka provides some great code at Ninject.Extensions.Logging.Log4net unexpected behavior, but when I try it, I get a compile error in the LoggerFactory at ILogger logger = new Logger(type); stating "Cannot access protected constructor 'Logger' here". Also, he states to "Tuck this whole mess away into a separate class library". Does that mean as a whole separate project?
I'm just getting lost in all the differing options and dated posts and would like any input on how to use Dependancy Injection with Ninject and Log4Net in my MVC3 project. Also, if it matters, all of my Ninject code is in my domain project, but the logging needs done from both the domain and web project (and mocked in my unit tests). Any help is appreciated.
You shouldn't have to configure anything except the normal log4net config.
All you have to do is to inject a ILogger wherever you want to log.
https://github.com/ninject/ninject.extensions.logging/wiki/Using

Resources