Dependency Injection in Domain Model Classes Using Nhibernate (ASP.NET MVC + IOC)

I am creating an ASP.NET MVC application that uses the DDD (Domain Driven Design) approach with database access handled by NHibernate. I have a domain model class (Administrator) in which I want to inject dependency through an IOC container such as Castle Windsor, something like this:

public class Administrator { public virtual int Id { get; set; } //.. snip ..// public virtual string HashedPassword { get; protected set; } public void SetPassword(string plainTextPassword) { IHashingService hasher = IocContainer.Resolve<IHashingService>(); this.HashedPassword = hasher.Hash(plainTextPassword); } } 

Basically, I want to use the IHashingService method for the SetPassword method without directly calling the IOC container (since this is supposedly an IOC anti-pattern). But I'm not sure how to do this. The My Admin object is either created through new Administrator(); , or loaded via NHibernate, so how can I add IHashingService to the Administrator class?

Secondly, am I going to do it right? I was hoping to avoid having my code base litter ...

 currentAdmin.Password = HashUtils.Hash(password, Algorithm.Sha512); 

... and instead, the domain model itself should take care of hashing and carefully encapsulate it. I can provide for another developer mistakenly choosing the wrong algorithm and having some passwords like Sha512, and some MD5, some with one salt, and some with another salt, etc. Etc. Instead, if the developers write ...

 currentAdmin.SetPassword(password); 

... then it will hide these details and take care of the problems listed above, right?

+7
asp.net-mvc inversion-of-control ioc-container nhibernate castle-windsor
source share
4 answers

There are similar questions about SO here:

Enabling Dependencies with NHibernate Objects

DI / IoC, NHibernate and help them work together

You will need to use Interceptors. Take a look at Fabio Molo's post for implementation:

http://nhforge.org/blogs/nhibernate/archive/2008/12/12/entities-behavior-injection.aspx

+5
source share

You need to remember how it was hashed. This means that you can hash the string in the future to check and see if it has a password by comparing this with the hashed value. This means that you need to store an enumeration or other field in your object that indicates the hash mechanism that was used in your database.

Otherwise, if you change the default hash implementation, all of your old hashed passwords are no longer good, and your users will scratch their heads about why their passwords no longer work - and you will get an IHashingService that does not provide flexibility (since the hashing implementation cannot be changed without adding weird rules, such as "use this hash for administrators created before 2010-01-12"), existing without a valid reason.

For this purpose, I would add an appropriate field (an enumeration, a string returned by the IHashingService interface, something), and either NHibernate will create a hash instance for me through the IUserType implementation, or I use the factory template where specific instances were provided by the factory with an IoC container. This will combine a Jarrett-level injection with a solution that allows re-hydrated objects to find their hash implementations, independent of the IoC container.

Good luck

+2
source share

Is there a reason why you cannot pass an IHashingService in the constructor for the Administrator class? The way I resolve addiction.

 public class Administrator { private readonly IHashingService _hashingService; public Administrator(IHashingService hashingService) { _hashingService = hashingService; } // <snip> public void SetPassword(string plainTextPassword) { this.HashedPassword = _hashingService.Hash(plainTextPassword); } } 

Edit # 1

If you are pulling out a model, try using method level injection.

 public void SetPassword(string plainText, IHashingService hasher) { if (hasher == null) throw new ArgumentNullException("hasher"); this.HashedPassword = hasher.Hash(plainText); } 

Edit # 2

Also, why don't you simplify and just do an extension per line?

 public static class ExtensionsOfString { public static string Hash(this string s) { // hash with SHA256 return hashedString; } } 

Although I understand that there is a β€œplug-in” code aspect of using dependency injection, this is not exactly what you need for this example. You really do not need an IPasswordEncryptionService the same way you need, for example, ICreditCardAuthorizationService. If you ever change your hash algorithm from SHA256 to SHA512, you will now invalidate every password in your database.

+1
source share

Any hash password in the application facet (if you use one) or supply an IHashingService implementation with every call to Administrator.SetPassword(..) . I think this is called double dispatch ?!

If you insist on a DI-in-entity solution, I did something similar with PostSharp AOP and PostSharp4Spring, declaring the [Configurable] attribute for the object, but the solution is for Spring.Net. You can look here for more information. Also, if you configure NHibernate from a DI container, you may fall into recursion by trying to execute a DI object before the container completes the configuration. You need a simple static class with a method to suppress DI when creating an object during container initialization. Unable to specify an example: (

+1
source share

All Articles