Ninject MVC together with WCF extension does not work with InRequestScope - asp.net-mvc

I have gotten Ninject MVC to work with Ninject WCF to get it to work I added two lines to CreateKernel method
kernel.Bind<ServiceHost>().To<NinjectServiceHost>();
KernelContainer.Kernel = kernel;
The dependencies are injected, but the Dispose method is not called, I've tried both with InRequestScope and doing my own scope Func return OperationContext.Current as Scope object, but the dispose is not called.
Update 2012-09-05
This info is obsolete, for MVC and WCF download from Nuget Ninject.MV3 and Ninject.Extensions.WCF (3.x) the MVC Nuget template will add a Ninject bootstrapper NinjectWebCommon.cs and to add support in a svc for ninject eddit the svc xml (Right click / View markup) and add Factory="Ninject.Extensions.Wcf.NinjectServiceHostFactory" to the xml node

I can't reply to Remo's answer because I'm a stackoverflow n00b but the issue with the 'System.Runtime.CompilerServices.ExtensionAttribute' exception is that it has moved from System.Core in .net 4.0 to mscorlib in .net 4.5. If you install .net 4.5 the problem disappears. I think something was built with .net 4.5 in the mix. https://github.com/ninject/Ninject.Web.Common/issues/3 Sounds like it will be fixed soon.
As for the Wcf InRequestScope issue Remo gave me some help today on the google groups...
"add a new module that derives from "Ninject.GlobalKernelRegistrationModule" and load it into the kernel. This will be fixed for the final release though."
i.e. something like...
public class MyModule : Ninject.GlobalKernelRegistrationModule<WcfRequestScopeCleanup>
{
}
//And where you load your modules...
kernel.Load<MyModule>();

I recommend using Ninject 3.0.0-rc2 available from Nuget. InRequestScope works for both Web and WCF requests side a side.

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");

Are there any undesirable side-effects from bootstrapping from an assembly without any services embedded in it?

I just installed MVC5 and ServiceStack.Host.Mvc into a empty ASP.NET project. MVC for the Routing, Bundling/Minification and ServiceStack for everything else (IoC, Cache, ect.). This site will only be used to deliver views (SPA Islands I call them) and these rendered views will in turn call another ServiceStack RESTful API site.
So my questions is this "Since I have to bootstrap ServiceStack with the AppHostBase which wants an assembly with a Service in it, is there any harm if I just use the current assembly with-out any services as the snippet below illustrates?"
public AppHost()
: base("Website UI", typeof(MyRootNamespace.Global).Assembly) { }
Everything still seems to work in controllers that inherit from ServiceStackController, at least the IoC.
Thank you,
Stephen
Nope, ServiceStack just uses the list of assemblies specified in the AppHost constructor to scan and autowire any IService's it can find in those assemblies, which in this case there just wont be any.

How to register custom build Autofac.Module in Orchard?

I have a piece of code that encapsulates functionality that isn't specific to Orchard. However i need to make it available in Orchard via dependency injection. So, I built up an Autofac Module that registers all components (types), but I can't find a way to inform Orchard's Autofac Container about it.
From what i red, there are two ways to add a module to a container:
By supplying the module at to the ContainerBuilder (usually at start-up),
Or by updating the already built Container at runtime with a ContainerBuilder
I can approach the problem in the first way, but I rather do a variant of the second if there is such?
Just add a class deriving from Autofac.Module to your Orchard module and that's it. It will get automatically picked by Orchard during the container construction.
Piotr Szmyd's answer is fundamentally correct, but here's some more detail:
Your Orchard Module is the new .csproj that you've added to the Orchard.sln
Add Autofac as a reference to that csproj (make sure you use the version included with Orchard - not nuget. See here for more details about that problem)
Then add a class that derives from Autofac.Module and which implements Load(ContainerBuilder).
e.g.
using System;
using Autofac;
namespace MyCustom.Module.Namespace
{
public class LoaderModule : Autofac.Module
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterType<MyClass>().As<IMyInterface>();
}
}
}
As an additional note:
The Autofac registration code only gets invoked at application startup time.
If you are running with the site sitting locally in IIS and the code in VS, then the dynamic compilation nature of Orcahrd means that when you recompile the code, the application doesn't stop.
So in order for this Autofac registration code to be hit (and also for any channges to it to take effect) you have to iisreset to kill the application, so that it reloads the Autofac Registrations.

Nhibernate (Fluent), Ninject.Mvc3, and Web Activator

I am working on an ASP .NET Mvc 3 App and have installed Ninject.Mvc3 using Nuget. I now have the App_Start folder and then ninject class. I have seen plenty of examples on how to configure NHibernate in the Global.asax file. So how do I configure the session before handing it Ninject if I am using the Web Activator class? Do I just do it like normal in the global.asax?,
Bob Cravens has a nice series of posts on how to do this:
Using the Repository Pattern with MVC and NHibernate
http://blog.bobcravens.com/2010/06/the-repository-pattern-with-linq-to-fluent-nhibernate-and-mysql/
Using an IoC container (like Ninject) with a NHibernate inside ASP.NET MVC
http://blog.bobcravens.com/2010/07/using-nhibernate-in-asp-net-mvc/
Any responsible web developer knows that managing / disposing of objects and resources is critical to good web application development. Please make sure and read this bit too :-)
http://blog.bobcravens.com/2010/11/using-ninject-to-manage-critical-resources/
I don't know which example you are refering to. But for most of them you can do it the same way.
Now, in App_Start folder you have a file called NinjectMVC.cs, there is a method:
private static void RegisterServices(IKernel kernel)
{
}
You have to register all your services there, just the same way you did in global.ascx before.

How to properly decouple Structure Map dependency resolver from ASP.NET MVC web project?

While developing web project using ASP.NET MVC, I came up against a coupling problem.
When I build custom controller factory (or dependency resolver if using MVC 3), I need this factory to know somehow where to get dependencies from. Here's my code:
//from Global.asax.cs
DependencyResolver.SetResolver(new StructureMapControllerFactory());
class StructureMapControllerFactory: IDependencyResolver {
Container repositories;
public StructureMapControllerFactory()
{
repositories = new RepositoriesContainer();
}
//... rest of the implementation
}
class RepositoriesContainer: Container
{
public RepositoriesContainer()
{
For<IAccountRepository>().Use<SqlAccountRepository>();
//...
}
}
StructureMapControllerFactory class is responsible for injecting dependencies into a controller. As I said, it needs to know where to find these dependencies (I mean concrete classes, like services and repositories implementations).
I have a separate class library called MySite.Data, where all the implementation details live. Contracts, like IAccountRepository, live in library MySite.Contracts. Now, if I reference this MySite.Data library directly from MVC project, there will be a dependency between my site and implementation of its data retrieval. The question is how can I remove it? What are best practices in this situation?
I'm sure it does have a bunch of workarounds, just I haven't found any yet.
Well, as I see it, you can't do exactly that. Your MVC project really really needs to know about concrete classes it is going to use.
You will anyway have to provide those container registrations somewhere and you'll get the dependency on the project/assembly where that type is defined. Shortly, you have to reference MySite.Data from MVC project. Like that:
MySite.Data knows nothing about MVC project
MVC project knows the concrete repositories types to provide correct container registrations.
You can make life simpler with StructureMap Registry objects but you need to include those Registries somewhere as well. Typically those are in the main project or some "StructureMap-adapter" project but you'd need to make reference anyway.
I'd advise that you:
Use MVC3 and drop your custom IControllerFactory if you only use it for DI into your Controllers.
Use StructureMap Registry objects to provide each and every IoC registration ever needed.
Use StructureMap Assembly scanning capabilities to provide components discovery.
Use something much more common as a DependencyResolver, i.e. not a StructureMapControllerFactory but a CommonServiceLocator with StructureMap adapter instead.
Try to abstract from StructureMap itself inside your main app.
And, of course, don't be afraid of making references inside the main project - they have nothing about coupling. It doesn't decrease maintainability. But the wrong architecture does, so be worried about that, not simple reference.

Resources