using a Handler in Web API and having Unity resolve per request - c#

I am using Unity as my IoC framework and I am creating a type based on the value in the header of each request in a handler:
var container = new UnityContainer();
container.RegisterType<IFoo,Foo>(new InjectionConstructor(valuefromHeader));
GlobalConfiguration.Configuration.DependencyResolver =
new Unity.WebApi.UnityDependencyResolver(container);
The problem is that the handler's SendAsync means that the global container is getting overwritten by different requests and the controllers that use IFoo in their constructor are getting the wrong values.
1) Can I make the SendAsync sync?
2) If not, how do I create different instances for each request and have the IoC container resolve safely?
I have looked at the following articles without success:
http://www.asp.net/web-api/overview/extensibility/using-the-web-api-dependency-resolver
http://www.strathweb.com/2012/11/asp-net-web-api-and-dependencies-in-request-scope/
http://benfoster.io/blog/per-request-dependencies-in-aspnet-web-api-using-structuremap
Thanks in advance.

I agree with #Steven's approach, but that doesn't answer your more general question of how to resolve per request.
I would recommend you change to using the UnityHierarchicalDependencyResolver and then anything you register with HierarchicalLifetimeManager will be resolved per request.
Change this...
GlobalConfiguration.Configuration.DependencyResolver =
new Unity.WebApi.UnityDependencyResolver(container);
to this...
GlobalConfiguration.Configuration.DependencyResolver =
new Unity.WebApi.UnityHierarchicalDependencyResolver(container);

The problem you are having is caused by you mixing runtime values with design time dependencies. In general, the services you resolve from the container should not depend on runtime values in their constructor. You shouldn't do this, because components tend to live much longer than runtime values and injecting runtime values into components, makes it much harder to diagnose and verify the container's configuration.
Instead, hide that value behind a service that can provide consumers with that instance when required. For instance:
public interface IHeaderValueProvider
{
HeaderValue GetCurrentValue();
}
You can create an implementation that can be easily registered and injected into any component that needs that value. Anytime after the construction phase, those components can call the GetCurrentValue() method on the injected IHeaderValueProvider dependency.

I managed to resolve per request by declaring my custom UnityResolver's class within the WebApiConfig class. The UnityResolver class uses the HttpConfiguration class assuming you're using an OWIN context.
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
var _container = new UnityContainer();
DependencyConfiguration.ConfigureContainer(_container);
config.DependencyResolver = new UnityResolver(_container);
}
The ConfigureContainer class is simply a class where I declare my IOC dependencies as shown below:
private static void RegisterReleaseEnv(IUnityContainer container)
{
//Repository Registration
container
.RegisterType(typeof(IRepository<>), typeof(GenericRepository<>), new HierarchicalLifetimeManager());
}
It is very important that you use the HierarchicalLifetimeManager lifetime manager so that you get a new instance per request.
The UnityResolver class then looks like this:
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();
}
}
I hope this helps.
For more information: http://www.asp.net/web-api/overview/advanced/dependency-injection

Related

MVC5 Web API and Dependency Injection

Trying to do some DI on Web API 2 without third-party tools.
So, from some examples I've got custom dependency resolver (why there's no integrated one? Strange, even Microsoft.Extensions.DependencyInjection provides nothing):
public class DependencyResolver : IDependencyResolver
{
protected IServiceProvider _serviceProvider;
public DependencyResolver(IServiceProvider serviceProvider)
{
this._serviceProvider = serviceProvider;
}
public IDependencyScope BeginScope()
{
return this;
}
public void Dispose()
{
}
public object GetService(Type serviceType)
{
return this._serviceProvider.GetService(serviceType);
}
public IEnumerable<object> GetServices(Type serviceType)
{
return this._serviceProvider.GetServices(serviceType);
}
public void AddService()
{
}
}
then created this class:
public class ServiceConfig
{
public static void Register(HttpConfiguration config)
{
var services = new ServiceCollection();
services.AddScoped<IMyService, MyServiceClient>();
var resolver = new DependencyResolver(services.BuildServiceProvider());
config.DependencyResolver = resolver;
}
}
and registered it:
protected void Application_Start()
{
GlobalConfiguration.Configure(WebApiConfig.Register);
GlobalConfiguration.Configure(ServiceConfig.Register);
}
But when I'm trying to use it:
public class TestController : ApiController
{
private IMyService _myService = null;
public TestController(IMyService myService)
{
_myService = myService;
}
public void Get()
{
_myService.DoWork();
}
}
I'm getting error:
An error occurred when trying to create a controller of type 'TestController'. Make sure that the controller has a parameterless public constructor.
How to cook this one in right way?
What you see happening is related to this problem. In short, Web API will call its default IHttpControllerActivator implementation to request a new controller instance. That instance will call into your DependencyResolver.GetService method. That method will forward the call to MS.DI's GetService method. However, since you didn't register your controllers into the MS.DI container, it will return null. This will cause the default IHttpControllerActivator to try to create the controller using reflection, but this requires a default constructor. Since the controller doesn't have one, this results in the rather cryptic exception message.
The quick solution, therefore, is to register your controllers, e.g.:
services.AddTransient<TestController>();
This, however, will only partly solve your problem because your IDependencyResolver implementation is broken. It is broken in an ugly way, because it might seem to work at first, but will result in memory leaks, because you always resolve from the root container, instead of resolving from a scope. This will cause your resolved controller instances (and other disposable transient components) to stay referenced for the lifetime of your application.
To fix this, you should change your IDependencyResolver implementation to the following:
public class DependencyResolver : IDependencyResolver
{
private readonly IServiceProvider provider;
private readonly IServiceScope scope;
public DependencyResolver(ServiceProvider provider) => this.provider = provider;
internal DependencyResolver(IServiceScope scope)
{
this.provider = scope.ServiceProvider;
this.scope = scope;
}
public IDependencyScope BeginScope() =>
new DependencyResolver(provider.CreateScope());
public object GetService(Type serviceType) => provider.GetService(serviceType);
public IEnumerable<object> GetServices(Type type) => provider.GetServices(type);
public void Dispose() => scope?.Dispose();
}
This implementation will ensure a new IServiceScope is created on each web request and services are always resolved from a request; not from the root IServiceProvider.
Although this will fix your problems, another implementation might still be benificial.
The IDependencyResolver contract is problematic, because it is forced to return null when a call to GetService doesn't result in the correct resolution of a registration. This means that you will end up with these annoying "Make sure that the controller has a parameterless public constructor" errors when you forget to register your controllers.
It is, therefore, much easier to create a custom IHttpControllerActivator instead. In that case you can call GetRequiredService which will never return null:
public class MsDiHttpControllerActivator : IHttpControllerActivator
{
private readonly ServiceProvider provider;
public MsDiHttpControllerActivator(ServiceProvider provider) =>
this.provider = provider;
public IHttpController Create(
HttpRequestMessage request, HttpControllerDescriptor d, Type controllerType)
{
IServiceScope scope = this.provider.CreateScope();
request.RegisterForDispose(scope); // disposes scope when request ends
return (IHttpController)scope.ServiceProvider.GetRequiredService(controllerType);
}
}
This MsDiHttpControllerActivator implementation can be added to the Web API pipeline as follows:
GlobalConfiguration.Configuration.Services
.Replace(typeof(IHttpControllerActivator),
new MsDiHttpControllerActivator(services.BuildServiceProvider(true)));
This removes the need to have an IDependencyResolver implementation. You still need to register your controllers, though:
services.AddTransient<TestController>();
Also note that I changed this:
services.BuildServiceProvider()
To this:
services.BuildServiceProvider(true)
This is a really important change; it protects you (for some part) against Captive Dependencies, which are one of the major problems when using DI Containers. For some obscure reason, the BuildServiceProvider() overload defaults to false, which means it will not validate your scopes.

How to write constructor when in an mvc api project

I am trying to write an API project in code first approach. I written some code but it shows error
An error occurred when trying to create a controller of type 'CatalogController'. Make sure that the controller has a parameterless public constructor.
and
Type Nop.Api.Controllers.CatalogController does not have a default constructor
Controller
public class CatalogController : ApiController
{
private readonly ICatalogModelFactory _catalogModelFactory;
public CatalogController(ICatalogModelFactory catalogModelFactory)
{
_catalogModelFactory = catalogModelFactory;
}
public HttpResponseMessage HomepageCategories()
{
HttpResponseMessage response = new HttpResponseMessage();
var model = _catalogModelFactory.PrepareHomepageCategoryModels();
var result = JsonConvert.SerializeObject(model);
response = new HttpResponseMessage(HttpStatusCode.OK) { Content = new StringContent(result) };
return response;
}
}
Can anyone please help me how solve this error? I am not getting what is wrong in the constructor part. When debugging this it is not hitting the breakpoint.
Why am I getting this error?
When you request a resource from a controller, the framework needs to process the request. So the routing identifies the controller, action etc. and then it needs to instantiate an instance of the controller in order to invoke the wanted method.
In order to do that, he will either need a public empty constructor or some way to resolve your constructor's dependencies.
In your case, you have one ctor that has a dependency of ICatalogModelFactory. The framework will need you to implement a Dependency Resolver and register you new resolver when the application starts (Global.asax) like this:
DependencyResolver.SetResolver(new MyDependencyResolver());
Here's and example of a UnityContainer custom dependency resolver as found in this link:
public class UnityDependencyResolver : IDependencyResolver
{
IUnityContainer container;
public UnityDependencyResolver(IUnityContainer container)
{
this.container = container;
}
public object GetService(Type serviceType)
{
try
{
return container.Resolve(serviceType);
}
catch
{
return null;
}
}
public IEnumerable<object> GetServices(Type serviceType)
{
try
{
return container.ResolveAll(serviceType);
}
catch
{
return new List<object>();
}
}
}
And the registration occurred in the Global.asax Application_Start method:
IUnityContainer container = GetUnityContainer();
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
By the way, another way to do so, is to create a ControllerFactory and simply resolve the controller with a DI container. I prefer using the dependency resolver for resolving controllers.

How to pass IoC container to NancyFX? (OWIN, Unity)

I have a Windows service where I use OWIN and NancyFX to host a website on top of it. On many places in my service, I use Unity to inject dependencies into classes, mostly services. However, if I use them in any Nancy modules, the dependencies get resolved twice because Nancy uses its own IoC container (TinyIoC).
Fortunately, Nancy allows to override the default IoC container generation and use of an existing one by creating a nancy bootstrapper. But how do I pass my existing IUnityContainer to the bootstrapper?
Basically, all I have to start OWIN is...
WebApp.Start<MyOwinStarter>(url);
How can I pass a Unity container to it to pass it further to the nancy bootstrapper?
#ccellar got me into the right direction.
I created a static class UnityHelper with the following methods:
private static Lazy<IUnityContainer> container = new Lazy<IUnityContainer>(() => {
var section = (UnityConfigurationSection)ConfigurationManager.GetSection("unityConfiguration");
return new UnityContainer().LoadConfiguration(section);
});
public static IUnityContainer GetConfiguredContainer() {
return container.Value;
}
Created a custom NancyBootstrapper class:
public NancyBootstrapper(IUnityContainer container) {
if(container == null)
throw new ArgumentNullException("container");
this._unityContainer = container;
}
protected override IUnityContainer GetApplicationContainer() {
return _unityContainer;
}
and passed the container to the bootstrapper in my web app startup class:
appBuilder.UseNancy(new NancyOptions {
EnableClientCertificates = true,
Bootstrapper
= new NancyBootstrapper(UnityHelper.GetConfiguredContainer())
});
Neat!
Disclaimer: I really don't know if this is the best/cleanest/whatever solution to this problem. But for me it works.
I wrapped my container (Castle Windsor) like this, which is basically a singleton.
public class Container
{
// static holder for instance, need to use lambda to construct since constructor private
private static readonly Lazy<IWindsorContainer> instance = new Lazy<IWindsorContainer>(() =>
{
var container = new WindsorContainer();
container.Install(FromAssembly.This());
return container;
});
// private to prevent direct instantiation.
private Container()
{
}
// accessor for instance
public static IWindsorContainer Instance
{
get
{
return instance.Value;
}
}
}
Then in my custom bootstrapper I access the already configured container like this
protected override Castle.Windsor.IWindsorContainer GetApplicationContainer()
{
return Container.Instance;
}
Actually, the easiest and correct way, would be to inherit a new bootstrapper class from the Bootstrapper type you are using - in your case WindsorNancyBootstrapper and override the GetApplicatioContainer method and return your instance
You can read more about it here
https://github.com/NancyFx/Nancy.bootstrappers.windsor#customizing

Castle Windsor/DelegatingHandler/IPrincipal Dependency Injection (DI)/Inversion of Control (IoC) in ASP.NET Web API

I decided to clean this post up and I posted a sample project at ge.tt/3EwoZEd/v/0?c
Spent around 30 hours on this already and still can't figure it out... help would be really appreciated!
I have an ASP.NET Web API solution that uses this code: http://www.piotrwalat.net/basic-http-authentication-in-asp-net-web-api-using-message-handlers/ to implement "Basic HTTP authentication in ASP.NET Web API using Message Handlers". I'm new to IoC/DI and I'm trying to get this to work with Castle Windsor.
I've been trying a lot of different things but I get 1 of the following errors depending on what I did wrong:
"Looks like you forgot to register the http module Castle.MicroKernel.Lifestyle.PerWebRequestLifestyleModule"
"Object reference not set to an instance of an object." for the PrincipalProvider in BasicAuthMessageHandler
"No component for supporting the service *.DummyPrincipalProvider was found"
Below is my code:
Global.asax.cs:
private static IWindsorContainer _container;
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
var config = (CustomErrorsSection)ConfigurationManager.GetSection("system.web/customErrors");
IncludeErrorDetailPolicy errorDetailPolicy;
switch (config.Mode)
{
case CustomErrorsMode.RemoteOnly:
errorDetailPolicy
= IncludeErrorDetailPolicy.LocalOnly;
break;
case CustomErrorsMode.On:
errorDetailPolicy
= IncludeErrorDetailPolicy.Never;
break;
case CustomErrorsMode.Off:
errorDetailPolicy
= IncludeErrorDetailPolicy.Always;
break;
default:
throw new ArgumentOutOfRangeException();
}
GlobalConfiguration.Configuration.IncludeErrorDetailPolicy = errorDetailPolicy;
ConfigureWindsor(GlobalConfiguration.Configuration);
GlobalConfiguration.Configuration.MessageHandlers.Add(new BasicAuthMessageHandler()
{
PrincipalProvider = _container.Resolve<IProvidePrincipal>()
});
}
public static void ConfigureWindsor(HttpConfiguration configuration)
{
// Create / Initialize the container
_container = new WindsorContainer();
// Find our IWindsorInstallers from this Assembly and optionally from our DI assembly which is in abother project.
_container.Install(FromAssembly.This());
_container.Kernel.Resolver.AddSubResolver(new CollectionResolver(_container.Kernel, true));
//Documentation http://docs.castleproject.org/Windsor.Typed-Factory-Facility.ashx
// Set the WebAPI DependencyResolver to our new WindsorDependencyResolver
var dependencyResolver = new WindsorDependencyResolver(_container);
configuration.DependencyResolver = dependencyResolver;
}
Windsor Installer:
public class PrincipalsInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(Classes.FromThisAssembly().BasedOn<DelegatingHandler>());
container.Register(
Component.For<IProvidePrincipal>().ImplementedBy<DummyPrincipalProvider>()
);
}
}
Modified DummyPrincipalProvider (from the original I got from the URL above):
public class DummyPrincipalProvider : IProvidePrincipal
{
private IUserRepository _userRepo;
public DummyPrincipalProvider(IUserRepository userRepo)
{
this._userRepo = userRepo;
}
public IPrincipal CreatePrincipal(string username, string password)
{
try
{
if (!this._userRepo.ValidateUser(username, password))
{
return null;
}
else
{
var identity = new GenericIdentity(username);
IPrincipal principal = new GenericPrincipal(identity, new[] { "User" });
if (!identity.IsAuthenticated)
{
throw new ApplicationException("Unauthorized");
}
return principal;
}
}
catch
{
return null;
}
}
}
WindsorDependencyResolver.cs:
internal sealed class WindsorDependencyResolver : IDependencyResolver
{
private readonly IWindsorContainer _container;
public WindsorDependencyResolver(IWindsorContainer container)
{
if (container == null)
{
throw new ArgumentNullException("container");
}
_container = container;
}
public object GetService(Type t)
{
return _container.Kernel.HasComponent(t) ? _container.Resolve(t) : null;
}
public IEnumerable<object> GetServices(Type t)
{
return _container.ResolveAll(t).Cast<object>().ToArray();
}
public IDependencyScope BeginScope()
{
return new WindsorDependencyScope(_container);
}
public void Dispose()
{
}
}
WindsorDependencyScope.cs:
internal sealed class WindsorDependencyScope : IDependencyScope
{
private readonly IWindsorContainer _container;
private readonly IDisposable _scope;
public WindsorDependencyScope(IWindsorContainer container)
{
if (container == null)
{
throw new ArgumentNullException("container");
}
_container = container;
_scope = container.BeginScope();
}
public object GetService(Type t)
{
return _container.Kernel.HasComponent(t) ? _container.Resolve(t) : null;
}
public IEnumerable<object> GetServices(Type t)
{
return _container.ResolveAll(t).Cast<object>().ToArray();
}
public void Dispose()
{
_scope.Dispose();
}
}
I assume IProvidePrincipal is your own implementation.
Best way, the only one IMHO, to use an IoC container is the Composition Root.
The entry point/composition root for web api has been well explained by ploeh's blog.
DelegatingHandler are not part of the "request resolving", so you may choose to resolve it within global asax Application_start where the container lives as private variable.
GlobalConfiguration.Configuration.MessageHandlers.Add(container.Resolve<BasicAuthMessageHandler>());
If you properly registered your handler and all its dependencies in the container, nothing else has to be done: handler instance you extracted from the container and added among MessageHandlers will have an IPrincipalProvider and (I)UserRepository. Keep in mind BasicAuthMessageHandler will act a singleton, so if you need a new instance of (I)UserRepository on each method call... you may consider TypedFactory to create your (I)UserRepository as late dependencies
Of course, any component starting from you top graph component have to be register in the container.
That's the easy way... in case you need somenthing more sophisticate, you may end up creating your "composition root" for DelegatingHandlers as well.
BTW: never, ever, doing somenthing like
UserRepository userRepo = new UserRepository();
or PrincipalProvider = new DummyPrincipalProvider()
none of the "Behaviour instance" should be created explicitly: container take care of providing right instance at the right time...
As per Jon Edit:
now DummyPrincipalProvider looks fine: just keep in mind since DummyPrincipalProvider is created among the message handler(act as singleton due to global registration), you are reusing always same instance.
Instead of your plumbing
var dependencyResolver = new WindsorDependencyResolver(_container);
configuration.DependencyResolver = dependencyResolver;
I rather use ploeh implementation(see above).
Your registration
container.Register(
Component.For<IProvidePrincipal>().ImplementedBy<DummyPrincipalProvider>()
.UsingFactoryMethod(kernel => kernel.Resolve<DummyPrincipalProvider>())
);
should be replaced with
container.Register(
Component.For<IProvidePrincipal>().ImplementedBy<DummyPrincipalProvider>()
);
that's wrong... container has to resolve it, not you explicitly
GlobalConfiguration.Configuration.MessageHandlers.Add(new BasicAuthMessageHandler());
stick with my configuration as above: BasicAuthMessageHandler resolved via container.
Let me know if it works.
PS: You registered the TypedFactory facility in the container, but you are not using it... just to let you know.
You registered DelegatingHandler(s) as Transient, but keep in mind they gonna be "singleton" by design: adding it to the MessageHandlers collection imply they gonna be reused on each request.
As per Jon Edit 2:
I added a sample on github. You should be able to build it and run it using NuGet Package Restore
Your issue about PerWebRequestdepends on the depencies of UserRepository on the NHibernate factory session creating session "PerWebRequest": you cannot resolve IPrincipalProvider->IUserRepository->ISession in Application_Start due to HttpContext. If you really need a IUserRepositry working w/ IPrincipalProvider dependency has to be to a IUserRepositoryFactory(TypedFactory) instead.
I tried to fix your sample using the typed factory and it works, but than I had an issue w/ NHibernate configuration and since I'm not an expert of that, I didn't go any further.
If you need help w/ the factory thing... LMK and I'll update my git sample using a factory within the DummyPrincipalProvider

How to configure Ninject to work with ServiceStack.net

In trying to configure ServiceStack.net to use Ninject as its IOC, I am getting errors referring to various bindings not being defined. Primarily for ICache Client.
What specific bindings need to be created to use Ninject properly?
Currently have specified:
Bind<ISessionFactory>().To<SessionFactory>();//Is this correct/needed?
Note
I have created an IContainerAdapter as per the ServiceStack documention to implement the use of Ninject.
(Found here:ServiceStack IOC Docs)
Note 2
My apphost configure method looks like this:
public override void Configure(Funq.Container container)
{
IKernel kernel = new StandardKernel(new BindingModule());
container.Adapter = new NinjectContainerAdapter(kernel);
}
Note 3
I have registered the ICacheClient as follows:
Bind().To();
And I am now getting an error pointing to IRequest
Error activating IRequestLogger\nNo matching bindings are available, and the type is not self-bindable
Container Adapter
public class NinjectContainerAdapter : IContainerAdapter
{
private readonly IKernel _kernel;
public NinjectContainerAdapter(IKernel kernel)
{
this._kernel = kernel;
}
public T TryResolve<T>()
{
return this._kernel.Get<T>();
}
public T Resolve<T>()
{
return this._kernel.Get<T>();
}
}
Have you injected your Container adapter with:
container.Adapter = new NinjectIocAdapter(kernel);
If so, try also make your AppHost class internal if you haven't done so. There should only be 1 instance of AppHost and some IOC's like to create their own instance, wiping out all the configuration from the first one.
The behavior you're getting sounds like Ninject is complaining about unresolved dependencies. Make sure you get Ninject to return null with Unresolved dependencies by using kernal.TryGet<T> in your Container Adapter, e.g:
public T TryResolve<T>()
{
return this._kernel.TryGet<T>();
}
You need to write your own IContainerAdapter and then set Container.Adapter in your AppHost

Categories

Resources