How can I automatically register all my fluent validators with Unity? - asp.net-mvc

Right now I've got my validators hooked up and building in my app, but every time we add a new validator we need to manually go into our Unity configuration and register the type. I'd like to do this automatically, much like this blog post describes doing with StructureMap, only for Unity instead.
Right now I've got something like this:
// in global.asax.cs
protected void Application_Start(Object sender, EventArgs e)
{
// some irrelevant registrations (area registrations, route config, etc)
var container = new UnityContainer();
UnityConfig.RegisterComponents(container);
FluentValidationModelValidatorProvider.Configure(c => c.ValidatorFactory = new UnityValidatorFactory(container));
}
public class UnityValidatorFactory : ValidatorFactoryBase
{
private readonly IUnityContainer container;
public UnityValidatorFactory(IUnityContainer container)
{
this.container = container;
}
public override IValidator CreateInstance(Type validatorType)
{
if (container.IsRegistered(validatorType))
{
return container.Resolve(validatorType) as IValidator;
}
return null;
}
}
public static class UnityConfig
{
public static void RegisterComponents(IUnityContainer container)
{
container.RegisterTypes(
AllClasses.FromAssemblies(
Assembly.GetAssembly(typeof (UnityConfig)),
WithMappings.FromMatchingInterface, WithName.Default);
RegisterValidators(container);
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}
private static void RegisterValidators(IUnityContainer container)
{
container.RegisterType<IValidator<MyFirstViewModel>, MyFirstViewModelValidator>();
container.RegisterType<IValidator<MySecondViewModel>, MySecondViewModelValidator>();
}
}
What I have is working, but I have to keep adding registrations to RegisterValidators() every time a new validator is created. Is there a way I can set this up to automatically detect and register all validators?

This turned out to be pretty easy once I figured out what I was doing, which maybe explains why Googling for the answer was yielding no results. I rewrote RegisterValidators as follows:
private static void RegisterValidators(IUnityContainer container)
{
var validators = AssemblyScanner.FindValidatorsInAssemblyContaining<OneOfMyValidators>();
validators.ForEach(validator => container.RegisterType(validator.InterfaceType, validator.ValidatorType));
}

You can let FV setup do the job for you, please refer to 1st comment here for more details from the contributers
public IServiceProvider ConfigureServices( IServiceCollection services )
{
services.AddAuthorization(options =>...);
services.AddMvc()
.AddFluentValidation( o =>
{
o.RegisterValidatorsFromAssemblyContaining<Startup>();
} );

Related

Dependency Injection in ApplicationEventHandler. Bug?

Umbraco v7.5.8
I have bunch of problems with DI setup (shown below).
1) Neither OnApplicationInitialized, nor OnApplicationStarted (and other) events firing if constructor takes parameter(s).
2) Backoffice is broken. It's not possible to access a content node. Exception message is:
An error occurred when trying to create a controller of type 'ContentController'. Make sure that the controller has a parameterless public constructor.
// Application handlers
public class UmbracoApplicationEventHandler : IApplicationEventHandler
{
private IMenuManager _menuManager;
public UmbracoApplicationEventHandler(IMenuManager menuManager)
{
_menuManager = menuManager;
}
public void OnApplicationStarting(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
{
ContentService.Saving += UpdateMenu;
}
private void UpdateMenu(IContentService sender, SaveEventArgs<IContent> saveEventArgs)
{
_menuManager.UpdateMenu();
}
}
// Unity config:
public static class UnityConfig
{
public static void RegisterComponents()
{
var container = new UnityContainer();
container.RegisterType<IMenuManager, MenuManager>();
GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);
}
}
// Owin Startup:
public class UmbracoStandardOwinStartup : UmbracoDefaultOwinStartup
{
public override void Configuration(IAppBuilder app)
{
//ensure the default options are configured
base.Configuration(app);
UnityConfig.RegisterComponents();
}
}
Please read: https://our.umbraco.org/documentation/reference/using-ioc.
You need to register and build your container on OnApplicationStarted event, not earlier if you want to make it work with Umbraco.

How to new up an object independent of the container? [duplicate]

I'm trying to implement IoC in my windows form application. My choice fell on Simple Injector, because it's fast and lightweight. I also implement unit of work and repository pattern in my apps. Here is the structure:
DbContext:
public class MemberContext : DbContext
{
public MemberContext()
: base("Name=MemberContext")
{ }
public DbSet<Member> Members { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();\
}
}
Model:
public class Member
{
public int MemberID { get; set; }
public string Name { get; set; }
}
GenericRepository:
public abstract class GenericRepository<TEntity> : IGenericRepository<TEntity>
where TEntity : class
{
internal DbContext context;
internal DbSet<TEntity> dbSet;
public GenericRepository(DbContext context)
{
this.context = context;
this.dbSet = context.Set<TEntity>();
}
public virtual void Insert(TEntity entity)
{
dbSet.Add(entity);
}
}
MemberRepository:
public class MemberRepository : GenericRepository<Member>, IMemberRepository
{
public MemberRepository(DbContext context)
: base(context)
{ }
}
UnitOfWork:
public class UnitOfWork : IUnitOfWork
{
public DbContext context;
public UnitOfWork(DbContext context)
{
this.context = context;
}
public void SaveChanges()
{
context.SaveChanges();
}
private bool disposed = false;
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
context.Dispose();
}
}
this.disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
MemberService:
public class MemberService : IMemberService
{
private readonly IUnitOfWork unitOfWork;
private readonly IMemberRepository memberRepository;
public MemberService(IUnitOfWork unitOfWork, IMemberRepository memberRepository)
{
this.unitOfWork = unitOfWork;
this.memberRepository = memberRepository;
}
public void Save(Member member)
{
Save(new List<Member> { member });
}
public void Save(List<Member> members)
{
members.ForEach(m =>
{
if (m.MemberID == default(int))
{
memberRepository.Insert(m);
}
});
unitOfWork.SaveChanges();
}
}
In Member Form I only add a textbox to input member name and a button to save to database. This is the code in member form:
frmMember:
public partial class frmMember : Form
{
private readonly IMemberService memberService;
public frmMember(IMemberService memberService)
{
InitializeComponent();
this.memberService = memberService;
}
private void btnSave_Click(object sender, EventArgs e)
{
Member member = new Member();
member.Name = txtName.Text;
memberService.Save(member);
}
}
I implement the SimpleInjector (refer to http://simpleinjector.readthedocs.org/en/latest/windowsformsintegration.html) in Program.cs as seen in the code below:
static class Program
{
private static Container container;
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Bootstrap();
Application.Run(new frmMember((MemberService)container.GetInstance(typeof(IMemberService))));
}
private static void Bootstrap()
{
container = new Container();
container.RegisterSingle<IMemberRepository, MemberRepository>();
container.Register<IMemberService, MemberService>();
container.Register<DbContext, MemberContext>();
container.Register<IUnitOfWork, UnitOfWork>();
container.Verify();
}
}
When I run the program and add a member, it doesn't save to database. If I changed container.Register to container.RegisterSingle, it will save to database. From the documentation, RegisterSingle will make my class to be a Singleton. I can't using RegisterLifeTimeScope because it will generate an error
"The registered delegate for type IMemberService threw an exception. The IUnitOfWork is registered as 'Lifetime Scope' lifestyle, but the instance is requested outside the context of a Lifetime Scope"
1) How to use SimpleInjector in Windows Form with UnitOfWork & Repository pattern?
2) Do I implement the patterns correctly?
The problem you have is the difference in lifestyles between your service, repository, unitofwork and dbcontext.
Because the MemberRepository has a Singleton lifestyle, Simple Injector will create one instance which will be reused for the duration of the application, which could be days, even weeks or months with a WinForms application. The direct consequence from registering the MemberRepository as Singleton is that all dependencies of this class will become Singletons as well, no matter what lifestyle is used in the registration. This is a common problem called Captive Dependency.
As a side note: The diagnostic services of Simple Injector are able to spot this configuration mistake and will show/throw a Potential Lifestyle Mismatch warning.
So the MemberRepository is Singleton and has one and the same DbContext throughout the application lifetime. But the UnitOfWork, which has a dependency also on DbContext will receive a different instance of the DbContext, because the registration for DbContext is Transient. This context will, in your example, never save the newly created Member because this DbContext does not have any newly created Member, the member is created in a different DbContext.
When you change the registration of DbContext to RegisterSingleton it will start working, because now every service, class or whatever depending on DbContext will get the same instance.
But this is certainly not the solution because having one DbContext for the lifetime of the application will get you into trouble, as you probably already know. This is explained in great detail in this post.
The solution you need is using a Scoped instance of the DbContext, which you already tried. You are missing some information on how to use the lifetime scope feature of Simple Injector (and most of the other containers out there). When using a Scoped lifestyle there must be an active scope as the exception message clearly states. Starting a lifetime scope is pretty simple:
using (ThreadScopedLifestyle.BeginScope(container))
{
// all instances resolved within this scope
// with a ThreadScopedLifestyleLifestyle
// will be the same instance
}
You can read in detail here.
Changing the registrations to:
var container = new Container();
container.Options.DefaultScopedLifestyle = new ThreadScopedLifestyle();
container.Register<IMemberRepository, MemberRepository>(Lifestyle.Scoped);
container.Register<IMemberService, MemberService>(Lifestyle.Scoped);
container.Register<DbContext, MemberContext>(Lifestyle.Scoped);
container.Register<IUnitOfWork, UnitOfWork>(Lifestyle.Scoped);
and changing the code from btnSaveClick() to:
private void btnSave_Click(object sender, EventArgs e)
{
Member member = new Member();
member.Name = txtName.Text;
using (ThreadScopedLifestyle.BeginScope(container))
{
var memberService = container.GetInstance<IMemberService>();
memberService.Save(member);
}
}
is basically what you need.
But we have now introduced a new problem. We are now using the Service Locator anti pattern to get a Scoped instance of the IMemberService implementation. Therefore we need some infrastructural object which will handle this for us as a Cross-Cutting Concern in the application. A Decorator is a perfect way to implement this. See also here. This will look like:
public class ThreadScopedMemberServiceDecorator : IMemberService
{
private readonly Func<IMemberService> decorateeFactory;
private readonly Container container;
public ThreadScopedMemberServiceDecorator(Func<IMemberService> decorateeFactory,
Container container)
{
this.decorateeFactory = decorateeFactory;
this.container = container;
}
public void Save(List<Member> members)
{
using (ThreadScopedLifestyle.BeginScope(container))
{
IMemberService service = this.decorateeFactory.Invoke();
service.Save(members);
}
}
}
You now register this as a (Singleton) Decorator in the Simple Injector Container like this:
container.RegisterDecorator(
typeof(IMemberService),
typeof(ThreadScopedMemberServiceDecorator),
Lifestyle.Singleton);
The container will provide a class which depends on IMemberService with this ThreadScopedMemberServiceDecorator. In this the container will inject a Func<IMemberService> which, when invoked, will return an instance from the container using the configured lifestyle.
Adding this Decorator (and its registration) and changing the lifestyles will fix the issue from your example.
I expect however that your application will in the end have an IMemberService, IUserService, ICustomerService, etc... So you need a decorator for each and every IXXXService, not very DRY if you ask me. If all services will implement Save(List<T> items) you could consider creating an open generic interface:
public interface IService<T>
{
void Save(List<T> items);
}
public class MemberService : IService<Member>
{
// same code as before
}
You register all implementations in one line using Batch-Registration:
container.Register(typeof(IService<>),
new[] { Assembly.GetExecutingAssembly() },
Lifestyle.Scoped);
And you can wrap all these instances into a single open generic implementation of the above mentioned ThreadScopedServiceDecorator.
It would IMO even be better to use the command / handler pattern (you should really read the link!) for this type of work. In very short: In this pattern every use case is translated to a message object (a command) which is handled by a single command handler, which can be decorated by e.g. a SaveChangesCommandHandlerDecorator and a ThreadScopedCommandHandlerDecorator and LoggingDecorator and so on.
Your example would then look like:
public interface ICommandHandler<TCommand>
{
void Handle(TCommand command);
}
public class CreateMemberCommand
{
public string MemberName { get; set; }
}
With the following handlers:
public class CreateMemberCommandHandler : ICommandHandler<CreateMemberCommand>
{
//notice that the need for MemberRepository is zero IMO
private readonly IGenericRepository<Member> memberRepository;
public CreateMemberCommandHandler(IGenericRepository<Member> memberRepository)
{
this.memberRepository = memberRepository;
}
public void Handle(CreateMemberCommand command)
{
var member = new Member { Name = command.MemberName };
this.memberRepository.Insert(member);
}
}
public class SaveChangesCommandHandlerDecorator<TCommand>
: ICommandHandler<TCommand>
{
private ICommandHandler<TCommand> decoratee;
private DbContext db;
public SaveChangesCommandHandlerDecorator(
ICommandHandler<TCommand> decoratee, DbContext db)
{
this.decoratee = decoratee;
this.db = db;
}
public void Handle(TCommand command)
{
this.decoratee.Handle(command);
this.db.SaveChanges();
}
}
And the form can now depend on ICommandHandler<T>:
public partial class frmMember : Form
{
private readonly ICommandHandler<CreateMemberCommand> commandHandler;
public frmMember(ICommandHandler<CreateMemberCommand> commandHandler)
{
InitializeComponent();
this.commandHandler = commandHandler;
}
private void btnSave_Click(object sender, EventArgs e)
{
this.commandHandler.Handle(
new CreateMemberCommand { MemberName = txtName.Text });
}
}
This can all be registered as follows:
container.Register(typeof(IGenericRepository<>),
typeof(GenericRepository<>));
container.Register(typeof(ICommandHandler<>),
new[] { Assembly.GetExecutingAssembly() });
container.RegisterDecorator(typeof(ICommandHandler<>),
typeof(SaveChangesCommandHandlerDecorator<>));
container.RegisterDecorator(typeof(ICommandHandler<>),
typeof(ThreadScopedCommandHandlerDecorator<>),
Lifestyle.Singleton);
This design will remove the need for UnitOfWork and a (specific) service completely.

Unable to perform dependency injection in MVC 5 Web API project using Castle Windsor

Below is the code for controller I want to instantiate using Windsor Castle.
public class TestController : ApiController
{
private ITestService _testService = null;
public TestController(ITestService testService)
{
_testService = testService;
}
public IList<TestClass> Get()
{
IList<TestClass> testObjects = _testService.GetAll().ToList();
return testObjects;
}
}
I've written following code in Global.asax.cs
protected void Application_Start()
{
........................
InitializeServiceLocator();
}
private static void InitializeServiceLocator()
{
_container = new WindsorContainer().Install(FromAssembly.This());
var controllerFactory = new WindsorControllerFactory(_container.Kernel);
ControllerBuilder.Current.SetControllerFactory(controllerFactory);
}
Here is the code for installer =>
public class ControllerInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
if (container == null)
{
throw new ArgumentNullException("container");
}
if (store == null)
{
throw new ArgumentNullException("store");
}
//All MVC controllers
container.Register(Classes.FromThisAssembly().BasedOn<IHttpController>().LifestylePerWebRequest());
AddComponentsTo(container);
}
private void AddComponentsTo(IWindsorContainer container)
{
container.Register(
///DBContext
Component.For<DbContext>().ImplementedBy<SCFEntities>().LifestyleTransient());
container.Register(
Classes.FromAssemblyNamed("MyProject.ApplicationServices").Pick().WithService.DefaultInterfaces().LifestylePerWebRequest(),
Classes.FromAssemblyNamed("MyProject.Data").Pick().WithService.DefaultInterfaces().LifestylePerWebRequest());
}
}
The problem is the controller instance is not created using parameterized constructor. It is expecting a parameterless constructor. Could anybody point out where I am going wrong? Thanks.
Be sure to read all the articles regarding WEB API that Mark Seemann wrote.
You can start here and then traverse the archive for Web API here.
Read the first article and then traverse the archive. Everything is here.

Web Api Start up Exceptions with IDependencyResolver implementation

I am developing a Web Api and I decided to use custom DependencyResolver. I refer this [Dependency Injection for Web API Controllers] article. Everything is working well so far in the terms of dependency injection into controllers. Code snippet of my configuration from my Owin startup class
private void RegisterIoC(HttpConfiguration config)
{
_unityContainer = new UnityContainer();
_unityContainer.RegisterType<IAccountService, AccountService>();
.........
.........
config.DependencyResolver = new UnityResolver(_unityContainer);
}
But at the time when Api starts for the very first time some ResolutionFailedException thrown (but catched) inside the UnityResolver's GetService method. Here is the exception message
"Exception occurred while: while resolving.
Exception is: InvalidOperationException -
The current type, System.Web.Http.Hosting.IHostBufferPolicySelector,
**is an interface and cannot be constructed. Are you missing a type mapping?**"
Above same exception thrown following types
System.Web.Http.Hosting.IHostBufferPolicySelector
System.Web.Http.Tracing.ITraceWriter
System.Web.Http.Metadata.ModelMetadataProvider
System.Web.Http.Tracing.ITraceManager
System.Web.Http.Dispatcher.IHttpControllerSelector
System.Web.Http.Dispatcher.IAssembliesResolver
System.Web.Http.Dispatcher.IHttpControllerTypeResolver
System.Web.Http.Controllers.IHttpActionSelector
System.Web.Http.Controllers.IActionValueBinder
System.Web.Http.Validation.IBodyModelValidator
System.Net.Http.Formatting.IContentNegotiator
I know that these ResolutionFailedException are thrown because I did not provide mappings in my unity configuration for above types.
Now here is my question :-, If I implement custom unity DependencyResolver I need to define mappings of above types and if need to define what will be their corresponding default implementation types OR is there some alternative way to implement DependencyResolver. I am really concerned even though application is running fine now, failing to resolve above type can cause serious issue later. Please help.
One final Addition:-
For following types, same ResolutionFailedException thrown when I make request for any action into the my web api
System.Web.Http.Dispatcher.IHttpControllerActivator
System.Web.Http.Validation.IModelValidatorCache
System.Web.Http.Controllers.IHttpActionInvoker
I was running in to the same issue using Unity with WebApi and OWIN/Katana.
The solution for me was to use the UnityDependencyResolver defined in the Unity.WebApi Nuget package instead of my own custom implementation (like #Omar Alani above)
Install-Package Unity.WebAPI
Note that the package will try and add a file named UnityConfig.cs in App_Start (the filename I used myself).
In that UnityConfig.cs file the package will add code to register the container against the GlobalConfiguration.Configuration.DependencyResolver which is not what we want with OWIN.
So instead of using:
GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);
Change to use:
config.DependencyResolver = new UnityDependencyResolver(container);
For completeness:
My UnityConfig.cs
public static class UnityConfig
{
public static void Register(HttpConfiguration config)
{
var container = new UnityContainer();
// Your mappings here
config.DependencyResolver = new UnityDependencyResolver(container);
}
}
My Startup.cs
[assembly: OwinStartup(typeof(UnityTest.BusinessLayer.Api.ApiStartup))]
namespace UnityTest.BusinessLayer.Api
{
public partial class ApiStartup
{
public void Configuration(IAppBuilder app)
{
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
HttpConfiguration httpConfig = new HttpConfiguration();
UnityConfig.Register(httpConfig);
ConfigureAuth(app); //In App_Start ->Startup.Auth
WebApiConfig.Register(httpConfig);
app.UseWebApi(httpConfig);
}
}
}
In case any of the above solutions still don't work for people, here's how I solved it.
After spending a day chasing down this error, it turned out to be some sort of VS caching issue. Out of desperation, I deleted all .suo files and force-get-latest, which seems to have resolved the issue.
This has been asked a long time ago, but I encountered a solution that wasn't mentioned here so maybe someone is still interested.
In my case, these exceptions were already caught internally by Unity (or whatever), but my Exception Settings in Visual Studio made them still show up. I just had to uncheck the "Break when this exception type is shown" check box and the application went on functioning normally.
The implementation of Unity.WebAPI is not very different from the one mentioned in the question. I liked the version referred to by the OP as it ignores only ResultionFailedException and lets the rest propagate up the stack. Unity.WebAPI suppresses all exceptions. What I'd do is ignore errors that we know are safe to do so and log (or rethrow) others.
public object GetService(Type serviceType)
{
try
{
return container.Resolve(serviceType);
}
catch(ResolutionFailedException ex)
{
if (!(typeof(System.Web.Http.Tracing.ITraceWriter).IsAssignableFrom(serviceType))
|| typeof(System.Web.Http.Metadata.ModelMetadataProvider).IsAssignableFrom(serviceType)
//...
))
{
// log error
}
}
return null;
}
Normally, you don't need to with Unity.
I use this implementation for IDependencyResolver with unity, and I don't have to register or map other than my interfaces/services.
public class UnityDependencyInjectionResolver : Disposable, IDependencyResolver
{
protected IUnityContainer Container;
public UnityDependencyInjectionResolver(IUnityContainer container)
{
if (container == null)
{
throw new ArgumentNullException("container");
}
Container = container;
}
public object GetService(Type serviceType)
{
try
{
return Container.Resolve(serviceType);
}
catch (ResolutionFailedException)
{
return null;
}
}
public T GetService<T>()
{
try
{
var serviceType = typeof(T);
return (T)Container.Resolve(serviceType);
}
catch (ResolutionFailedException)
{
return default(T);
}
}
public T GetService<T>(string name)
{
try
{
var serviceType = typeof (T);
return (T) Container.Resolve(serviceType, name);
}
catch (ResolutionFailedException)
{
return default(T);
}
}
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 UnityDependencyInjectionResolver(child);
}
protected override void DisposeManagedResources()
{
if (Container == null)
{
return;
}
Container.Dispose();
Container = null;
}
}
where Disposable is just a base class implements IDispoable.
Hope that helps.
As this seems to still get disputed, here's my version of the code...
/// <summary>
/// Specifies the Unity configuration for the main container.
/// </summary>
public class UnityConfig
{
private static Lazy<IUnityContainer> container = new Lazy<IUnityContainer>(() =>
{
var container = new UnityContainer();
RegisterTypes(container);
return container;
});
/// <summary>
/// Gets the configured Unity container.
/// </summary>
public static IUnityContainer GetConfiguredContainer()
{
return container.Value;
}
public static void RegisterTypes(IUnityContainer container)
{
// Keeping this separate allows easier unit testing
// Your type mappings here
}
}
and
[assembly: OwinStartup(typeof(UnityTest.BusinessLayer.Api.ApiStartup))]
namespace UnityTest.BusinessLayer.Api
{
public static HttpConfiguration Config { get; private set; }
public partial class ApiStartup
{
public void Configuration(IAppBuilder app)
{
// IoC
var container = UnityConfig.GetConfiguredContainer();
var resolver = new UnityHierarchicalDependencyResolver(container); // Gets us scoped resolution
app.UseDependencyResolverScope(resolver); // And for the OWIN
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
// NB Must be before WebApiConfig.Register
ConfigureAuth(app); //In App_Start ->Startup.Auth
// See http://stackoverflow.com/questions/33402654/web-api-with-owin-throws-objectdisposedexception-for-httpmessageinvoker
// and http://aspnetwebstack.codeplex.com/workitem/2091
#if SELFHOST
// WebAPI configuration
Config = new HttpConfiguration
{
DependencyResolver = resolver
};
WebApiConfig.Register(Config);
app.UseWebApi(Config);
#else
GlobalConfiguration.Configuration.DependencyResolver = resolver;
// http://stackoverflow.com/questions/19907226/asp-net-webapi-2-attribute-routing-not-working
// Needs to be before RouteConfig.RegisterRoutes(RouteTable.Routes);
GlobalConfiguration.Configure(WebApiConfig.Register);
Config = GlobalConfiguration.Configuration;
#endif
// Now do MVC configuration if appropriate
}
}
}
Finally bits are the extensions to use the scoped container in the Owin middleware as well as straight WebAPI
public static class AppBuilderExtensions
{
public static IAppBuilder UseDependencyResolverScope(this IAppBuilder app, IDependencyResolver resolver)
{
return app.Use<DependencyResolverScopeMiddleware>(resolver);
}
}
/// <summary>
/// Wraps middleware in a <see cref="IDependencyResolver"/> scope.
/// </summary>
public class DependencyResolverScopeMiddleware : OwinMiddleware
{
private readonly IDependencyResolver resolver;
public DependencyResolverScopeMiddleware(OwinMiddleware next, IDependencyResolver resolver) : base(next)
{
this.resolver = resolver;
}
public override async Task Invoke(IOwinContext context)
{
using (var scope = resolver.BeginScope())
{
context.SetDependencyScope(scope);
await Next.Invoke(context);
}
}
}
The rationale for this is the original MVC Work Item where we see
kichalla wrote Oct 27, 2014 at 4:34 PM
Yes...right...UseWebApi extension should be used only with
self-hosting scenarios...since we are all on the same page, I am
closing this issue as by-design...please let us know if you have any
more questions...
Thanks, Kiran
and
kichalla wrote Oct 29, 2014 at 5:28 PM
#thebothead: Thanks for finding this out!...right, this sample
shouldn't have been using Microsoft.AspNet.WebApi.Owin in IIS as it
was never intended to be used in that host...we will investigate the
issue further to see why this exception happens...but meanwhile you
could follow the approach mentioned in the sample that I provided
earlier...
Thanks, Kiran
From my own experience if you don't use this form of the code, it will work in debug etc but will not scale and start behaving strangely.
I has deleted dependencyResolver and this problem was solved
public static class UnityConfig
{
public static void Register(HttpConfiguration config)
{
var container = new UnityContainer();
// Your mappings here
config.DependencyResolver = null;
}
}

Castle Windsor IoC in an MVC application

Prepare for a wall of code... It's a long read, but it's as verbose as I can get.
In response to Still lost on Repositories and Decoupling, ASP.NET MVC
I think I am starting to get closer to understanding this all.
I'm trying to get used to using this. Here is what I have so far.
Project
Project.Web (ASP.NET MVC 3.0 RC)
Uses Project.Models
Uses Project.Persistence
Project
Project.Models (Domain Objects)
Membership.Member
Membership.IMembershipProvider
Project
Project.Persistence (Fluent nHibernate)
Uses Project.Models
Uses Castle.Core
Uses Castle.Windsor
Membership.MembershipProvider : IMembershipProvider
I have the following class in Project.Persistence
using Castle.Windsor;
using Castle.MicroKernel.Registration;
using Castle.MicroKernel.SubSystems.Configuration;
namespace Project.Persistence
{
public static class IoC
{
private static IWindsorContainer _container;
public static void Initialize()
{
_container = new WindsorContainer()
.Install(
new Persistence.Containers.Installers.RepositoryInstaller()
);
}
public static T Resolve<T>()
{
return _container.Resolve<T>();
}
}
}
namespace Persistence.Containers.Installers
{
public class RepositoryInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(
Component
.For<Membership.IMembershipProvider>()
.ImplementedBy<Membership.MembershipProvider>()
.LifeStyle.Singleton
);
}
}
}
Now, in Project.Web Global.asax Application_Start, I have the following code.
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
// Register the Windsor Container
Project.Persistence.IoC.Initialize();
}
Now then, in Project.Web.Controllers.MembershipController I have the following code.
[HttpPost]
public ActionResult Register( Web.Models.Authentication.Registration model)
{
if (ModelState.IsValid)
{
var provider = IoC.Resolve<Membership.IMembershipProvider>();
provider.CreateUser(model.Email, model.Password);
}
// If we got this far, something failed, redisplay form
return View(model);
}
So I am asking first of all..
Am I on the right track?
How can I use Castle.Windsor for my ISessionFactory
I have my SessionFactory working like this ...
namespace Project.Persistence.Factories
{
public sealed class SessionFactoryContainer
{
private static readonly ISessionFactory _instance = CreateSessionFactory();
static SessionFactoryContainer()
{
}
public static ISessionFactory Instance
{
get { return _instance; }
}
private static ISessionFactory CreateSessionFactory()
{
return Persistence.SessionFactory.Map(#"Data Source=.\SQLEXPRESS;Initial Catalog=FluentExample;Integrated Security=true", true);
}
}
}
namespace Project.Persistence
{
public static class SessionFactory
{
public static ISessionFactory Map(string connectionString, bool createSchema)
{
return FluentNHibernate.Cfg.Fluently.Configure()
.Database(FluentNHibernate.Cfg.Db.MsSqlConfiguration.MsSql2008
.ConnectionString(c => c.Is(connectionString)))
.ExposeConfiguration(config =>
{
new NHibernate.Tool.hbm2ddl.SchemaExport(config)
.SetOutputFile("Output.sql")
.Create(/* Output to console */ false, /* Execute script against database */ createSchema);
})
.Mappings(m =>
{
m.FluentMappings.Conventions.Setup(x =>
{
x.AddFromAssemblyOf<Program>();
x.Add(FluentNHibernate.Conventions.Helpers.AutoImport.Never());
});
m.FluentMappings.AddFromAssemblyOf<Mapping.MembershipMap>();
}).BuildSessionFactory();
}
So basically, within my Project.Persistence layer, I call the SessionFactory like this..
var session = SessionFactoryContainer.Instance.OpenSession()
Am I even getting close to doing this right? I'm still confused - I feel like the ISessionFactory should be part of Castle.Windsor, but I can't seem to figure out how to do that. I'm confused also about the way I am creating the Repository in the Controller. Does this mean I have to do all of the 'mapping' each time I use the Repository? That seems like it would be very resource intensive.
Firstly some conceptual details. In an ASP.NET MVC application the typical entry point for a page request is a controller. We want the Inversion of Control container to resolve our controllers for us, because then any dependencies that the controllers have can also be automatically resolved simply by listing the dependencies as arguments in the controllers' constructors.
Confused yet? Here's an example of how you'd use IoC, after it is all set up. I think explaining it this way makes things easier!
public class HomeController : Controller
{
// lets say your home page controller depends upon two providers
private readonly IMembershipProvider membershipProvider;
private readonly IBlogProvider blogProvider;
// constructor, with the dependencies being passed in as arguments
public HomeController(
IMembershipProvider membershipProvider,
IBlogProvider blogProvider)
{
this.membershipProvider = membershipProvider;
this.blogProvider = blogProvider;
}
// so taking your Registration example...
[HttpPost]
public ActionResult Register( Web.Models.Authentication.Registration model)
{
if (ModelState.IsValid)
{
this.membershipProvider.CreateUser(model.Email, model.Password);
}
// If we got this far, something failed, redisplay form
return View(model);
}
}
Note that you have not had to do any resolving yourself, you have just specified in the controller what the dependencies are. Nor have you actually given any indication of how the dependencies are implemented - it's all decoupled. It's very simple there is nothing complicated here :-)
Hopefully at this point you are asking, "but how does the constructor get instantiated?" This is where we start to set up your Castle container, and we do this entirely in the MVC Web project (not Persistence or Domain). Edit the Global.asax file, setting Castle Windsor to act as the controller factory:
protected void Application_Start()
{
//...
ControllerBuilder.Current
.SetControllerFactory(typeof(WindsorControllerFactory));
}
...and define the WindsorControllerFactory so that your controllers are instantiated by Windsor:
/// Use Castle Windsor to create controllers and provide DI
public class WindsorControllerFactory : DefaultControllerFactory
{
private readonly IWindsorContainer container;
public WindsorControllerFactory()
{
container = ContainerFactory.Current();
}
protected override IController GetControllerInstance(
RequestContext requestContext,
Type controllerType)
{
return (IController)container.Resolve(controllerType);
}
}
The ContainerFactory.Current() method is static singleton that returns a configured Castle Windsor container. The configuration of the container instructs Windsor on how to resolve your application's dependencies. So for example, you might have a container configured to resolve the NHibernate SessionFactory, and your IMembershipProvider.
I like to configure my Castle container using several "installers". Each installer is responsible for a different type of dependency, so I'd have a Controller installer, an NHibernate installer, a Provider installer for example.
Firstly we have the ContainerFactory:
public class ContainerFactory
{
private static IWindsorContainer container;
private static readonly object SyncObject = new object();
public static IWindsorContainer Current()
{
if (container == null)
{
lock (SyncObject)
{
if (container == null)
{
container = new WindsorContainer();
container.Install(new ControllerInstaller());
container.Install(new NHibernateInstaller());
container.Install(new ProviderInstaller());
}
}
}
return container;
}
}
...and then we need each of the installers. The ControllerInstaller first:
public class ControllerInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(
AllTypes
.FromAssembly(Assembly.GetExecutingAssembly())
.BasedOn<IController>()
.Configure(c => c.Named(
c.Implementation.Name.ToLowerInvariant()).LifeStyle.PerWebRequest));
}
}
... and here is my NHibernateInstaller although it is different to yours, you can use your own configuration. Note that I'm reusing the same ISessionFactory instance every time one is resolved:
public class NHibernateInstaller : IWindsorInstaller
{
private static ISessionFactory factory;
private static readonly object SyncObject = new object();
public void Install(IWindsorContainer container, IConfigurationStore store)
{
var windsorContainer = container.Register(
Component.For<ISessionFactory>()
.UsingFactoryMethod(SessionFactoryFactory));
}
private static ISessionFactory SessionFactoryFactory()
{
if (factory == null)
{
lock (SyncObject)
{
if (factory == null)
{
var cfg = new Configuration();
factory = cfg.Configure().BuildSessionFactory();
}
}
}
return factory;
}
}
And finally you'll want to define your ProvidersInstaller:
public class ProvidersInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
var windsorContainer = container
.Register(
Component
.For<IMembershipProvider>()
.ImplementedBy<SubjectQueries>())
.Register(
Component
.For<IBlogProvider>()
.ImplementedBy<SubjectQueries>());
// ... and any more that your need to register
}
}
This should be enough code to get going! Hopefully you're still with me as the beauty of the Castle container becomes apparent very shortly.
When you define your implementation of your IMembershipProvider in your persistence layer, remember that it has a dependency on the NHibernate ISessionFactory. All you need to do is this:
public class NHMembershipProvider : IMembershipProvider
{
private readonly ISessionFactory sessionFactory;
public NHMembershipProvider(ISessionFactory sessionFactory)
{
this.sessionFactory = sessionFactory;
}
}
Note that because Castle Windsor is creating your controllers and the providers passed to your controller constructor, the provider is automatically being passed the ISessionFactory implementation configured in your Windsor container!
You never have to worry about instantiating any dependencies again. Your container does it all automatically for you.
Finally, note that the IMembershipProvider should be defined as part of your domain, as it is defining the interface for how your domain behaviours. As noted above, the implementation of your domain interfaces which deal with databases are added to the persistence layer.
Avoid using a static IoC class like this. By doing this you're using the container as a service locator, so you won't achieve the full decoupling of inversion of control. See this article for further explanations about this.
Also check out Sharp Architecture, which has best practices for ASP.NET MVC, NHibernate and Windsor.
If you have doubts about the lifecycle of the container itself, see Usage of IoC Containers; specifically Windsor

Resources