I'm using Ninject.MVC3 with WebAPI.
Originally, I was using the implementation of NinjectResolver and NinjectScope as outlined here,i.e. using _kernel.BeginBlock(),
I noticed that BeginBlock() gets invoked on each call to the Controller. On load testing the controller (over several hundred invocations) I noticed that the memory consumption of w3wp increased significantly (upwards of 1.4 gigs on high load) and the GC would never reclaim any memory.
Per this SO post, the kernel should not be disposed and BeginBlock() should not be used. Following which I updated the Resolver and Scope like so:
public class NinjectScope : IDependencyScope
{
protected IResolutionRoot resolutionRoot;
public NinjectScope(IResolutionRoot kernel)
{
resolutionRoot = kernel;
}
public object GetService(Type serviceType)
{
IRequest request = resolutionRoot.CreateRequest(serviceType, null, new Parameter[0], true, true);
return resolutionRoot.Resolve(request).SingleOrDefault();
}
public IEnumerable<object> GetServices(Type serviceType)
{
IRequest request = resolutionRoot.CreateRequest(serviceType, null, new Parameter[0], true, true);
return resolutionRoot.Resolve(request).ToList();
}
public void Dispose()
{
//Don't dispose the kernel
//IDisposable disposable = (IDisposable)resolutionRoot;
//if (disposable != null) disposable.Dispose();
//resolutionRoot = null;
}
}
public class NinjectResolver : NinjectScope, IDependencyResolver
{
private IKernel _kernel;
public NinjectResolver(IKernel kernel): base(kernel)
{
_kernel = kernel;
}
public IDependencyScope BeginScope()
{
return new NinjectScope(_kernel);
//what's the difference between using just _kernel vs _kernel.BeginBlock()
//return new NinjectScope(_kernel.BeginBlock());
}
}
The memory consumption lowered significantly following this change(i.e. using the above implementation). I would like to understand why this is.
What is it that BeginBlock() really does and when should one use it.
Is the above implementation accurate?
Remo Gloor says that the ActivationBlock concept is broken and that you should not use them. Furthermore, issues regarding ActivationBlock will most likely not going to be fixed, as the feature is to be removed from future Ninject versions.
The idea of Activation Blocks (current implementation) is:
Create exactly one instance of every type requested in the ActivationBlock
dispose of all instances created by the ActivationBlock when the block itself is disposed.
Also see:
https://github.com/ninject/ninject/issues/106
Future of Activation Blocks
Furthermore, you've tagged & named your question with "MVC3" but the System.Web.Http.Dependencies.IDependencyResolver interface you are using is related to asp.net-web-api. MVC's System.Web.Mvc.IDependencyResolver is different.
Ninject already features nuget packages which do the integration into asp.net-mvc-3 (4,5,...) and asp.net web api:
Ninject.MVC3
WebApi
Now if you really want to implement the dependency resolver and scope yourself we can compare it to ninject's web-api implementation:
NinjectDependencyResolver.cs
which inherits from NinjectDependencyScope.cs
The only real difference to your code is that they have one class implementing both, IDependencyResolver and IDependencyScope and that they are consistently using the IResolutionRoot instead of the IKernel interface.
(and for comparison: MVC3 NinjectDependencyResolver.cs)
Related
Since MvvmCross v7 sticks on its own IoC container, I would like to replace it with the .NET Core one in order to have an easier life when registering third party libraries such as IHttpClientFactory, Polly, Automapper, etc. through already built-in extensions methods.
To achieve this, I've successfully created a class that implementas MvxSingleton<IMvxIoCProvider> described as follow:
public class HostingAdapter : MvxSingleton<IMvxIoCProvider>, IMvxIoCProvider
{
private IServiceProvider ServiceProvider;
private IServiceCollection ServiceCollection;
public HostingAdapter()
{
var host = Host
.ConfigureServices((context, serviceCollection) =>
{
// Configure local services
ConfigureServices(context, serviceCollection);
ServiceCollection = serviceCollection;
ServiceProvider = ServiceCollection.BuildServiceProvider();
})
.Build();
}
public void RegisterType<TFrom, TTo>() where TFrom : class where TTo : class, TFrom
{
ServiceCollection.AddTransient<TFrom, TTo>();
ServiceProvider = ServiceCollection.BuildServiceProvider();
}
public T GetSingleton<T>() where T : class
{
return ServiceProvider.GetRequiredService<T>();
}
public object GetSingleton(Type type)
{
return ServiceProvider.GetRequiredService(type);
}
.. and all the required methods requested by the interface.
Then on the platform specific side I override the IoC creation as follow:
protected override IMvxIoCProvider CreateIocProvider()
{
var hostingAdapter = new HostingAdapter();
return hostingAdapter;
}
The code seems to work but as soon as the app starts Mvx registers its own "extra" services such as the IMvxLoggerProvider, IMvxSettings and so on. And here issues come:
ServiceProvider = ServiceCollection.BuildServiceProvider(); is called during the Host initialization but Mvx still continue to register services after that. This means IServiceProvider is not 'in sync' with IServiceCollection and a new ServiceCollection.BuildServiceProvider(); call is needed. I temporarily solved updating the provider at each collection registration (like the code above) but I'm aware this affects performances. Anyone knows how to workaround this?
There are plenty of Mvx services that are not registered so the app fails to start. These are the IMvxLogProvider, IMvxAndroidLifetimeMonitor, IIMvxSettings, IMvxStart, etc. I just wonder, why? How can let Mvx handle the registration in my container of all what it needs to start? I partially solved some of them such as the logger thing replacing the default with a custom one, but other callbacks like InitializeLifetimeMonitor are called too late for being registered.
Do I need to change anything in my MvxApplication than the most standard implementation?
Am I really forced to replace the standard IoC container? How can I handle the IServiceCollection's extension methods that 3rd party libraries expose like services.AddHttpClient();?
If it needs, I am on Xamarin classic using the Droid platform. Thanks
Deliberately inspired by Unity.Microsoft.DependencyInjection repository I've workarounded this approaching the problem the other way round: instead of replacing the default IoC container, I manually initialize an IServiceCollection instance and I add it to the Mvx's IoC provider.
To achieve this, I've used the following code:
public class App : MvxApplication
{
public override void Initialize()
{
base.Initialize();
InitializeServiceCollection();
CreatableTypes()
.EndingWith("Service")
.AsInterfaces()
.RegisterAsLazySingleton();
RegisterAppStart<HomeViewModel>();
}
private static void InitializeServiceCollection()
{
IServiceCollection serviceCollection = new ServiceCollection();
ConfigureServices(serviceCollection);
IServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
MapServiceCollectionToMvx(serviceProvider, serviceCollection);
}
private static void ConfigureServices(IServiceCollection serviceCollection)
{
serviceCollection.AddHttpClient();
}
private static void MapServiceCollectionToMvx(IServiceProvider serviceProvider,
IServiceCollection serviceCollection)
{
foreach (var serviceDescriptor in serviceCollection)
{
if (serviceDescriptor.ImplementationType != null)
{
Mvx.IoCProvider.RegisterType(serviceDescriptor.ServiceType, serviceDescriptor.ImplementationType);
}
else if (serviceDescriptor.ImplementationFactory != null)
{
var instance = serviceDescriptor.ImplementationFactory(serviceProvider);
Mvx.IoCProvider.RegisterSingleton(serviceDescriptor.ServiceType, instance);
}
else if (serviceDescriptor.ImplementationInstance != null)
{
Mvx.IoCProvider.RegisterSingleton(serviceDescriptor.ServiceType, serviceDescriptor.ImplementationInstance);
}
else
{
throw new InvalidOperationException("Unsupported registration type");
}
}
}
}
I've got a class that requires access to the HttpRequestMessage in my Web API service. At the moment, I've got the following code to capture the message in the pipeline and save it for later (based on this and this):
public class ContextCapturingControllerActivator : IHttpControllerActivator
{
private readonly IKernel kernel;
private HttpRequestMessage requestMessage;
public ContextCapturingControllerActivator(IKernel kernel)
{
this.kernel = kernel;
}
public IHttpController Create(HttpRequestMessage requestMessage,
HttpControllerDescriptor controllerDescriptor,
Type controllerType)
{
this.kernel.Rebind<HttpRequestMessage>()
.ToConstant<HttpRequestMessage>(requestMessage);
var controller = (IHttpController)this.kernel.GetService(controllerType);
this.requestMessage = requestMessage;
requestMessage.RegisterForDispose(
new Release(() => this.kernel.Release(controller)));
return controller;
}
private class Release : IDisposable
{
private readonly Action release;
public Release(Action release)
{
this.release = release;
}
public void Dispose()
{
this.release();
}
}
}
In my composition root, I configure the ControllerActivator:
kernel.Bind<IHttpControllerActivator>()
.To<ContextCapturingControllerActivator>();
The end result is that from the perspective of the configuration, the HttpRequestMessage is "magically" injected wherever it is requested since it is done for us inside the ControllerActivator. I have not been able to inject the message from my composition root. I'm also not crazy about the Rebind since it's there to avoid adding a new binding every time the service is called. I suspect it's due to the singleton nature of the Web API stack, but have not been able to sort out how to deal with that properly.
In general, I cannot use the latest unstable Nuget package of Ninject web api due to the error reported (and ignored) here.
Can anyone suggest the proper way to improve my code to make it a bit more clear and make life easier for future maintainers (and let's face it -- that's probably going to be me).
Thanks.
Here is what I did, but I believe it depends on Web API 2.0+.
I created an instance class that wraps the current context's http request:
public class HttpRequestMessageWrapper
{
private readonly HttpRequestMessage m_httpRequestMessage;
public HttpRequestMessageWrapper()
{
m_httpRequestMessage = HttpContext.Current.Items["MS_HttpRequestMessage"] as HttpRequestMessage;
}
public HttpRequestMessage RequestMessage
{
get
{
return m_httpRequestMessage;
}
}
}
Then I bound the HttpRequestMessage to the property with the ToMethod binding in request scope.
container.Bind<HttpRequestMessage>().ToMethod(ctx => new HttpRequestMessageWrapper().RequestMessage).InRequestScope();
I've tried the method that #Mackers proposed which is the cleanest way.... however, in my specific scenario, it didn't work due to a timing issue. For my case, I needed to inject an object into the apicontroller ctor and that object required the HttpRequestMessage. The HttpContext.Current.Items["MS_HttpRequestMessage"]isn't populated until the controller has been constructed and initialized and I couldn't find any other way to access it. So I resorted to creating a custom DelegatingHandler and rebinding the current request message as they come in.
public class CurrentHttpRequestMessageHandler : DelegatingHandler
{
[SecuritySafeCritical]
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
UpdateScopeWithHttpRequestMessage(request);
return base.SendAsync(request, cancellationToken);
}
internal static void UpdateScopeWithHttpRequestMessage(HttpRequestMessage request)
{
NinjectConfig.GetConfiguredKernel().Rebind<HttpRequestMessage>().ToMethod(ctx => { return request; })
.InRequestScope();
}
}
The GetConfiguredKernel is a static method I created to simply return the static Kernel instance already configured.
public class NinjectConfig
{
private static readonly Bootstrapper bootstrapper = new Bootstrapper();
private static StandardKernel _kernel;
public static void Start()
{
DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
bootstrapper.Initialize(CreateKernel);
}
public static IKernel GetConfiguredKernel()
{
if (_kernel != null)
return _kernel;
return CreateKernel();
}
....
Then register the DelegatingHandler with the HttpConfiguration:
config.MessageHandlers.Add(new CurrentHttpRequestMessageHandler());
Building off of Macker's answer, System.Web has an HttpRequestBase class that you can use and simplify unit testing the code. Anywhere in the code that the request is required, specify the HttpRequestBase type as the constructor parameter and register it with the below method:
Ninject example:
Bind<HttpRequestBase>().ToMethod(context => new HttpRequestWrapper(HttpContext.Current.Request));
Unity example:
container.RegisterType<HttpRequestBase>(new InjectionFactory(_ => new HttpRequestWrapper(HttpContext.Current.Request)));
I'm trying to build an implementation of the IHttpControllerActivator interface for with with StructureMap, so that I can resolve a dependency of a controller which takes a dependency on the HttpRequestMessage being processed in the MVC Web API pipeline.
My implementation of Create is as follows:
public IHttpController Create(
HttpRequestMessage request,
HttpControllerDescriptor controllerDescriptor,
Type controllerType)
{
return (IHttpController)this.Container
.With(request)
.With(controllerDescriptor)
.GetInstance(controllerType);
}
The Container property is a reference to the StructureMap IContainer instance passed to the activator when it is constructed.
My registration for the controllers uses reflection to obtain all the ApiController implementations:
foreach(var controller in this.GetType().Assembly.GetTypes()
.Where(type => typeof(ApiController).IsAssignableFrom(type)))
{
this.For(controller).Use(controller);
}
Using the debugger, I checked that initialises the controller instances and passes in their dependencies. However, when the ExecuteAsync method is called on the controller, an exception is thrown:
Cannot reuse an 'ApiController' instance. 'ApiController' has to be constructed per incoming message. Check your custom 'IHttpControllerActivator' and make sure that it will not manufacture the same instance.
After some digging and experimentation I discovered this is due to a check performed at the start of ExecuteAsync which checks the Request property of the ApiController to see if it has been assigned a value. If the property has a non-null value, it infers that the controller has already been used to process a request and aborts the operation.
Further to this, I verified that StructureMap attempted to use its setter-injection behaviour when composing the controller and is responsible for Request having a non-null value.
In my registry, I haven't configured any setter-injection, so I'm confused as to why it's being invoked here. A poke around the StructureMap API hasn't yielded any obvious answers as to how I could change the behaviour exhibited.
Am I invoking StructureMap incorrectly? Is there a configuration setting I can leverage to say "never ever assign a property value"?
I think your issue revolves around the way that you are setting up your controllers with StructureMap. In order to get this working correctly, the best way is to hook into the WebAPI stack's dependency injection stack by creating your own implementation of IDependencyResolver. There's a pretty good example of this at http://craigsdevspace.wordpress.com/2012/02/26/using-structuremap-with-web-api/
The basic code, though, might look something like:
IDependencyResolver:
public class _DependencyResolver : _DependencyScope, IDependencyResolver {
public _DependencyResolver(IContainer container) : base(container) { }
public IDependencyScope BeginScope() {
return new _DependencyScope(_container);
}
}
IDependencyScope:
public class _DependencyScope : ServiceLocatorImplBase, IDependencyScope {
protected readonly IContainer _container;
public _DependencyScope(IContainer container) {
if (container == null)
throw new ArgumentNullException("container");
_container = container;
}
public override object GetService(Type serviceType) {
if (serviceType == null)
return null;
try {
return (serviceType.IsAbstract || serviceType.IsInterface)
? _container.TryGetInstance(serviceType)
: _container.GetInstance(serviceType);
} catch {
return null;
}
}
protected override object DoGetInstance(Type serviceType, string key) {
if (string.IsNullOrEmpty(key))
return _container.TryGetInstance(serviceType);
return _container.TryGetInstance(serviceType, key);
}
protected override IEnumerable<object> DoGetAllInstances(Type serviceType) {
return _container.GetAllInstances<object>().Where(s => s.GetType() == serviceType);
}
public IEnumerable<object> GetServices(Type serviceType) {
return _container.GetAllInstances<object>().Where(s => s.GetType() == serviceType);
}
public void Dispose() {
//_container.Dispose();
}
}
To hook these classes up to WebAPI, then, you would add the following to Global.asax:
GlobalConfiguration.Configuration.DependencyResolver =
new _DependencyResolver(ObjectFactory.Container);
And either in Global.asax or in your Bootstrapper, you would add the following:
ObjectFactory.Initialize(x => {
x.Scan(scanner => scanner.AddAllTypesOf<ApiController>());
});
This sets up your StructureMap implementation to use the stack's pre-existing injection structure - which should avoid the problem that you're having.
I have an MVC3 project that uses Ninject, Entity Framework and the Unit of Work pattern with a Service layer.
My AsyncService class has a function that starts a background task that, as an example, adds users to the User repository.
My current problem is that the task only runs correctly for a few seconds before I get an error that the DbContext has been disposed.
My database context, which is injected with Ninject's InRequestScope() seems to be getting disposed, as InRequestScope() ties it to HttpContext.
I've read about InThreadScope(), however I'm not sure how to implement it properly in my MVC project.
My Question is: What is the correct way to use Ninject in my Task?
public class AsyncService
{
private CancellationTokenSource cancellationTokenSource;
private IUnitOfWork _uow;
public AsyncService(IUnitOfWork uow)
{
_uow = uow;
}
public void AsyncStartActivity(Activity activity)
{
...snip...
this.cancellationTokenSource = new CancellationTokenSource();
var cancellationToken = this.cancellationTokenSource.Token;
var task = Task.Factory.StartNew(() =>
{
foreach (var user in activity.UserList)
{
this._uow.UserRepository.Add(new User() {UserID = user});
}
this._uow.Save();
}, cancellationToken);
...snip...
}
}
InRequestScope'd objects are Disposed at the end of a request so it can't be used in this case. InThreadScope also doesn't fit as that would reuse the UoW for several tasks.
What you can do though is declare your AsyncService as the Scoping Object for all the objects within using the NamedScope extension.
See http://www.planetgeek.ch/2010/12/08/how-to-use-the-additional-ninject-scopes-of-namedscope/
This is a messy solution that I've used in the past using the ChildKernel plugin (I think Named scope would much cleaner). Basically I create a child kernel, and scope everything pertaining to the UoW as singleton in the child kernel. I then create a new child kernel for each Task, handle the UoW, and commit or rollback.
IAsyncTask is an interface with 1 method, Execute()
private Task void ExecuteTask<T>() where T:IAsyncTask
{
var task = Task.Factory.StartNew(() =>
{
var taskKernel = _kernel.Get<ChildKernel>();
var uow = taskKernel.Get<IUnitOfWork>();
var asyncTask = taskKernel.Get<T>();
try
{
uow.Begin();
asyncTask.Execute();
uow.Commit();
}
catch (Exception ex)
{
uow.Rollback();
//log it, whatever else you want to do
}
finally
{
uow.Dispose();
taskKernel.Dispose();
}
});
return task;
}
I would like to experiment with NServiceBus using ASP.NET MVC 3. I've got a solution with NServiceBus installed, plus NinjectMVC3 and NServiceBus.Ninject-CI. Trouble is, I have no idea how to setup NServiceBus stuff in the NinjectMVC3.cs file in App_Start.
Rather annoyingly I'm having trouble finding any examples of how to use NServiceBus.Ninject-CI (I hate it when people don't bother giving examples of how to use their stuff).
Can someone help me get started please?
Load a module like this into the kernel to provide access to the bus
public class NServiceBusModule : NinjectModule
{
public override void Load()
{
this.Bind<IBus>().ToConstant(this.CreateBus()).InSingletonScope();
}
private IBus CreateBus()
{
return NServiceBus.Configure.WithWeb()
.NinjectBuilder(this.Kernel)
... // put NServiceBus config here
.CreateBus()
.Start();
}
}
Read the NServiceBus documentation about how to configure NServiveBus:
http://docs.particular.net/nservicebus/containers/ninject
http://docs.particular.net/samples/web/asp-mvc-application/
Hopefully this will help someone. I had a lot of trouble finding sample code for getting ninject working within NServiceBus.
This code below works for me in place of the more common Castle version:
public class EndpointConfig : IConfigureThisEndpoint, AsA_Publisher, IWantCustomInitialization
{
#region IWantCustomInitialization Members
public void Init()
{
Configure
.With()
.NinjectBuilder(CreateKernel())
.XmlSerializer()
.MsmqTransport();
SetLoggingLibrary.Log4Net(XmlConfigurator.Configure);
}
protected IKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Load<MyCustomNinjectModule>();
return kernel;
}
#endregion
}
with the ninject module being the usual format, ie:
public class MyCustomNinjectModule : NinjectModule
{
public override void Load()
{
Bind(typeof(ILogger<>)).To(typeof(Log4NetLogger<>));
...
}
}