ASP.Net MVC 3 Unity 2.0 IoC - asp.net-mvc-3

I am about to go live with an application I have built using ASP.Net MVC 3 and Entity Framework 4.1. For dependency injection I used the Unity 2.0 IoC. I used this tutorial as a guide to help setup the Unity IoC http://weblogs.asp.net/shijuvarghese/archive/2011/01/21/dependency-injection-in-asp-net-mvc-3-using-dependencyresolver-and-controlleractivator.aspx
Today I was checking through my code for any last minute bug fixes and I came across the
Application_Start() method in my Global.asax file. It looks something like this
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
IUnityContainer container = new UnityContainer();
container.RegisterType<IControllerActivator, CustomControllerActivator>(new HttpContextLifetimeManager<IControllerActivator>());
//container.RegisterType<IUnitOfWork, UnitOfWork>(new ContainerControlledLifetimeManager());
container.RegisterType<IUnitOfWork, UnitOfWork>(new HttpContextLifetimeManager<IUnitOfWork>());
container.RegisterType<IListService, ListService>(new HttpContextLifetimeManager<IListService>());
container.RegisterType<IShiftService, ShiftService>(new HttpContextLifetimeManager<IShiftService>());
}
The application is working fine, but I noticed I was missing the line of code
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
Which goes after the line
IUnityContainer container = new UnityContainer();
As I say, my application was working fine (locally anyway) without this line of code. I have since added it and the application is again working as expected.
However, I am a bit worried that my Unity IoC wasn’t setup correctly. Why did my application work even without this additional line of code? And do I even need to add it?
Thanks for your help.
Update
Below shows the constructor for one of my Controllers
public class AccountController : Controller
{
private IAccountService _accountService;
private IUserService _userService;
private IFormsAuthenticationService _formsService;
private INotificationService _notifyService;
private ILoggingService _logService;
public AccountController(ILoggingService logService, IAccountService accountService, IUserService userService, IFormsAuthenticationService formsService, INotificationService notifyService)
{
_accountService = accountService;
_userService = userService;
_formsService = formsService;
_notifyService = notifyService;
_logService = logService;
}

Folks
Please ignore this question. I found out that the line
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
was included in my code after all.
Note to self - look harder at your code next time!!!

Related

Windsor transient lifestyle

I have some very odd behaviour in my Windsor Container.
I have configured my container like this.
Container = new WindsorContainer();
Container.Kernel.ComponentModelCreated += KernelComponentModelCreated;
Container.Install(FromAssembly.This());
private static void KernelComponentModelCreated(ComponentModel model)
{
if (model.LifestyleType == LifestyleType.Undefined)
model.LifestyleType = LifestyleType.Transient;
}
So I was supposing all my components where I don't specify the lifestyle would get a transient lifestyle and it seemed to don't give any issues until now.
I start multiple asynchronous task which all resolve some components. (So you would expect every task gets a new instance of the component)
However now I know the tasks don't get new instances, because my tasks fail because of crossthreading issues with the component. (so it is being used in multiple tasks)
When I replace the Container.Resolve(somecomponent); With just creating the new component in place everything works like it should.
var contextProvider = MvcApplication.Container.Resolve<IDbContextProvider>();
replaced with
var contextProvider = new DbContextProvider();
So my question is what am I missing here.
The tasks are started in transient configured MVC3 controllers, because of explicitly configured.
The DbContextProvider is resolved in all repositories also configured transient, because of above code.
Another thing I found in the documentation is. You have to release transient components. I implemented all components with IDisposable. But because of auto contructor injection in my controllers I am not completely sure if I have to release them manually and if so how can I do this. (Yes I know I have to call the Release method on the container)
UPDATE
Code below is responsible for releasing and resolving my controllers:
public class WindsorControllerFactory : DefaultControllerFactory
{
private readonly IKernel _kernel;
public WindsorControllerFactory(IKernel kernel)
{
_kernel = kernel;
}
public override void ReleaseController(IController controller)
{
_kernel.ReleaseComponent(controller);
}
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
if (controllerType == null)
{
throw new HttpException(404, string.Format("The controller for path '{0}' could not be found.", requestContext.HttpContext.Request.Path));
}
return (IController)_kernel.Resolve(controllerType);
}
}
Is there some example available for testing if all dependencies are resolved and released the way they should be? (LifeStyle tests)
I'm not sure if this is what is causing your issues, but you should modify ComponentModel in an implementation of IContributeComponentModelConstruction only.
Check out the documentation of the component model construction contributors for help on how to effectively change the default lifestyle of the container.
Regarding disposal of IDisposables - if you release your controller like you should everything will just work with Windsor :)

ASP.Net MVC 3 project with Ninject and HierarchicalLifetimeManager?

First of all, dependency injection is relatively new to me. I did a first project using Unity.MVC3, and now I would like to switch to Ninject on a new project, since it seems to be the most popular dependency injector for .Net projects. So now, I am trying to use Ninject v2.2.1.4 with Ninject.MVC3 v2.2.2.0 in my project.
In my previous project where I was using Unity, I had something like the following code in my Bootstrapper class:
private static IUnityContainer BuildUnityContainer()
{
var container = new UnityContainer();
container.RegisterType<ITestService, TestService>();
container.RegisterType<IDatabaseFactory, DatabaseFactory>(new HierarchicalLifetimeManager());
container.RegisterType<IUnitOfWork, UnitOfWork>();
container.RegisterType<ILoggingService, LoggingService>();
container.RegisterControllers();
return container;
}
Now, I my new project, I replaced this with something like the following code in the NinjectMVC3 class (App_Start):
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<ITestService>().To<TestService>();
//This does not compile:
//kernel.Bind<IDatabaseFactory>().To<DatabaseFactory>(new HierarchicalLifetimeManager());
kernel.Bind<IDatabaseFactory>().To<DatabaseFactory>();
kernel.Bind<IUnitOfWork>().To<UnitOfWork>();
kernel.Bind<ILoggingService>().To<LoggingService>();
}
However, I don't know what I should do with the DatabaseFactory binding, since it normally requires the use of HierarchicalLifetimeManager. Can anyone tell me how to properly create the binding for DatabaseFactory?
First of all, add these references bu NuGet to be sure that you have a compatible set of packages.
Then, if you add the Ninject.Web.MVC it will setup the project initialization code for you through a power shell script.
And last make a BindModule class like this and add it to module in CreateKernel method that have been created in second step.
public class BindModule : NinjectModule
{
public override void Load()
{
this.Bind<IControllerActivator>().To<CustomControllerActivator>().InRequestScope();
this.Bind<MembaseClient>().ToMethod(context => new MembaseClient()).InSingletonScope();
this.Bind<IUnitOfWork>().To<UnitOfWork>().InRequestScope();
this.Bind<ISessionFactory>().ToMethod(o => MyAutoMapper.sessionFactory).InSingletonScope();
this.Bind<ISession>().ToMethod(o => MyAutoMapper.sessionFactory.OpenSession()).InRequestScope();
}
}
Part of NinjectMVC3 class
public static class NinjectMVC3
{
/// <summary>
/// Creates the kernel that will manage your application.
/// </summary>
/// <returns>The created kernel.</returns>
private static IKernel CreateKernel()
{
var modules = new NinjectModule[] { new BindModule() };
var kernel = new StandardKernel(modules);
RegisterServices(kernel);
return kernel;
}
}
As you can see above Ninjet has built in functions to take care of different life cycles for each object.

Unittesting MVC controller

Im trying to learn MVC combined with IoC and DI. In my project I also use Castle, Automapper, NHibernate, NHibernateIntegration.
Thanks to the excellent example "ToBeSeen" app by Kozmic I think I have the solution pretty much set up now. But now I want to unittest basic save operation at the controller method level. I just dont get how to go about this. I expect my problem is pretty simple but Im a novice at this and any help is appreciated.
I have a dossiercontroller like this:
[Authorize]
[Transactional]
public class DossierController : BaseController
{
private readonly IRepository repository;
private readonly IMappingEngine mappingEngine;
private readonly ILogger logger;
public DossierController(IRepository repository, IMappingEngine mappingEngine, ILogger logger)
{
this.repository = repository;
this.mappingEngine = mappingEngine;
this.logger = logger;
}
As you can see it needs a repostitory, mappingengine and logger. As I understand all this is configured and wired up at runtime.
Next I have a controller method that is used to save a dossier:
[HttpPost]
[ActionName("Dossier")]
[Transaction]
[AcceptVerbs(HttpVerbs.Post)]
[AcceptParameter(Name = "button", Value = "save")]
public ActionResult Dossier_Save(string button, DossierModel dossierModel, string returnUrl)
{
if (!Request.IsAuthenticated)
return RedirectToAction("Index", "Home");
if (!ModelState.IsValid) return View(dossierModel);
Dossier dossier = mappingEngine.Map<DossierModel, Dossier>(dossierModel);
repository.Save(dossier);
return View();
}
Here I just want to automap the dossiermodel into a dossier and save it using the repository.
Now I want to unit test this using Nunit. I dont want to mock anything, I want a real persistence test from the controller level. For this I have to create a new dossiercontroller and pass in the correct arguments. Now Im lost. How do I create and configure the arguments so they work exactly like in the web application. For instance: How do I create a correctly configured Automapper in a Unittest? How do I create a correctly configured repository? Should I use a container?
Any help, especcialy a code example is highly appreciated!
Thanks in advance.
If you don't want to mock anything, you will need to instantiate concrete versions of the services required by the constructor of your controller.
e.g.
IRepository repository = GetRepository();
IMappingEngine mappingEngine = GetMappingEngine();
ILogger logger = GetLogger();
DossierController controller = new DossierController(repository, mappingEngine, logger);
ActionResult rsult = controller.Save(...etc...);
As to how you are to configure and instantiate these, you will essentially need to do this in exactly the same way that your MVC app is doing this.
If you are unsure where in your MVC app these are being configured, I'd suggest that the first place to look is in the IoC configuration and work backword from there.

MVC Controller - Inject 2 repositories in controller

I'm trying to inject a second repository into my asp.net mvc 3 controller. And I cant get it to work, not sure where to "add another" using Ninject.
I have a void function in global.asa.cs
kernel.Bind<INewsRepository>().To<NewsRepository>();
And in my controller I have:
private INewsRepository _newsRepository;
private IContentRepository _contentRepository;
public NewsController(INewsRepository newsRepository, IContentRepository contentRepository)
{
this._newsRepository = newsRepository;
this._contentRepository = contentRepository;
}
How can I register IContentRepository for the NewsController as well?
I use autofac instead of Ninject but the basics stay the same.
If you got your first dependency injection working then you should be able to bind others as well. You just have to add a new binding in Application_Start() in your Global.asax.
So under your first binding do this as well:
kernel.Bind<IContentRepository>().To<ContentRepository>();
You can have as many bindings as you like.
First off it's a good practice to move the bootstrapping of your application into a separate location. This keeps your Global.asax clean.
You should also be using convention based registration. It will end up saving you lots of time for the bindings you don't need to customize.
So for you I'd probably suggest the following
public static class Bootstrapper()
{
public static void Bootstrap()
{
kernel.Scan( k =>
{
k.FromAssemblyContaining<INewsRepository>();
k.BindWithDefaultConventions();
});
}
}
And in your Global.asax you add this..
Bootstrapper.Bootstrap();
Then I would suggest you spend some time on Google reading about ninject conventions.

Getting SNAP(AOP), NInject and ASP.Net MVC 3 working together

Has anyone got the SNAP AOP framework working with MVC 3 and Ninject.
The samples given when adding Snap using NuGet to an MVC 3 project don't specifcally work well with a previously added NInject package. I have tried to get it working based on the normal NInject approach but just cannot get it to actually intercept!
Can anyone show how to do this in code please?
I figured it out with the latest version of Ninject through NuGet which now adds a class call NinjectMVC3 in a new AppStart folder in the MVC3 application.
The code I used is as folows:
In the automatically created NinjectMVC3.cs CreateKernel() method:-
private static IKernel CreateKernel()
{
// Wire it up with AOP
NinjectAopConfiguration.NinjectAopConfigure();
//var kernel = new StandardKernel(); // Removed
RegisterServices(NinjectAopConfiguration._container.Kernel);
return NinjectAopConfiguration._container.Kernel;
}
I also wired up Ninject for the various injection targets in RegisterServices() method.
Next I took the sample code generated by NuGet when adding SNAP.Ninject to the MVC 3 application, renamed it NinjectAOP.cs and made it look like this:
public static class NinjectAopConfiguration
{
public readonly static NinjectAspectContainer _container;
static NinjectAopConfiguration()
{
_container = new NinjectAspectContainer();
}
public static void NinjectAopConfigure()
{
SnapConfiguration.For(_container).Configure(c =>
{
c.IncludeNamespace("MyNamespace.Model.*");
c.Bind<ExceptionLoggingInterceptor>().To<ExceptionLoggingAttribute>();
});
}
}
I also needed to do an assembly binding redirect for Ninject as follows because there is an assembly version conflict somewhere for Ninject:
I hope this helps someone.
I invite anyone to have a look and see if they can improve this please.

Resources