Note that there are some explanatory texts on larger screens.

plurals
  1. POUsing Unity.BuildUp in one class breaks injection in other class
    text
    copied!<p>I've got a membership provider that creates a problem with dependency injection. <strong>I would like to understand why it happens</strong>. </p> <p>This is some parts of a base controller. (It works like it should.)</p> <pre><code>namespace Our.Web.Controllers { public abstract partial class OurBaseController : VABController { //-------------------------------------- // EVENT DECLARATIONS //-------------------------------------- //-------------------------------------- // CLASS CONSTANTS //-------------------------------------- //-------------------------------------- // PRIVATE VARIABLES //-------------------------------------- private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); private UserInfo m_info; //-------------------------------------- // PROTECTED VARIABLES //-------------------------------------- //-------------------------------------- // CONSTRUCTOR &amp; INITIALIZATION //-------------------------------------- protected override void Initialize(System.Web.Routing.RequestContext requestContext) { base.Initialize(requestContext); logger.Debug("Initializing OurBaseController."); m_info = UserInfoAccessor.GetCurrent(); } //-------------------------------------- // GETTER/SETTERS //-------------------------------------- [Dependency] public UserInfoAccessor UserInfoAccessor { get; set; } &lt;snip&gt; } } </code></pre> <p>Here's the relevant parts of the unity registration from Global.asax.cs:</p> <pre><code>namespace OurWeb { public class MvcApplication : System.Web.HttpApplication, IContainerAccessor { &lt;snip&gt; //-------------------------------------- // GETTER/SETTERS //-------------------------------------- IUnityContainer IContainerAccessor.Container { get { return MvcUnityContainer.Container ; } } //-------------------------------------- // EVENT HANDLERS //-------------------------------------- protected void Application_Start() { AreaRegistration.RegisterAllAreas(); RegisterRoutes(RouteTable.Routes); ConfigureUnity(); &lt;snip&gt; } &lt;snip&gt; //-------------------------------------- // STATIC METHODS //-------------------------------------- &lt;snip&gt; //-------------------------------------- // PRIVATE &amp; PROTECTED INSTANCE METHODS //-------------------------------------- private void ConfigureUnity() { //Create UnityContainer IUnityContainer container = new UnityContainer() &lt;snip&gt; .RegisterType&lt;UserInfoAccessor&gt;() &lt;snip&gt; //Set container for Controller Factory MvcUnityContainer.Container = container; &lt;snip&gt; //Set Controller Factory as UnityControllerFactory ControllerBuilder.Current.SetControllerFactory( typeof(UnityControllerFactory)); } &lt;snip&gt; } } </code></pre> <p>Now when I add a custom membership provider, I couldn't inject into it, so I have used BuildUp in the constructor.</p> <pre><code>namespace System.Web.Security { public class OurMembershipProvider : SqlMembershipProvider { //-------------------------------------- // EVENT DECLARATIONS //-------------------------------------- //-------------------------------------- // CLASS CONSTANTS //-------------------------------------- //-------------------------------------- // PRIVATE VARIABLES //-------------------------------------- private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); //-------------------------------------- // PROTECTED VARIABLES //-------------------------------------- //-------------------------------------- // CONSTRUCTOR &amp; INITIALIZATION //-------------------------------------- public OurMembershipProvider() : base() { // Can't inject so we'll ask the container to build the instance. IUnityContainer container = GetUnityContainer(); container.BuildUp(this); } //-------------------------------------- // GETTER/SETTERS //-------------------------------------- [Dependency] public UserInfoAccessor UserInfoAccessor { get; set; } //-------------------------------------- // PUBLIC METHODS //-------------------------------------- public override bool ValidateUser(string username, string password) { //Sufficient for the question. In reality it contains account mapping validation logic. return base.ValidateUser(username, password); } //-------------------------------------- // EVENT HANDLERS //-------------------------------------- //-------------------------------------- // STATIC METHODS //-------------------------------------- //-------------------------------------- // PRIVATE &amp; PROTECTED INSTANCE METHODS //-------------------------------------- private IUnityContainer GetUnityContainer() { var context = HttpContext.Current; if (context == null) throw new Exception("No HttpContext"); var accessor = context.ApplicationInstance as IContainerAccessor; if (accessor == null) throw new Exception("The global HttpApplication instance needs to implement " + typeof(IContainerAccessor).FullName); if (accessor.Container == null) throw new Exception("HttpApplication has no container initialized"); return accessor.Container; } } } </code></pre> <p>The class resides in the MVC web project so I've just changed the web.config like this:</p> <pre><code>&lt;!--&lt;add name="AspNetSqlMembershipProvider" type="System.Web.Security.SqlMembershipProvider, System.Web" connectionStringName="ApplicationServices" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="false" passwordFormat="Hashed" maxInvalidPasswordAttempts="5" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10" passwordStrengthRegularExpression="" applicationName="/"/&gt;--&gt; &lt;add name="AspNetSqlMembershipProvider" type="System.Web.Security.OurMembershipProvider" connectionStringName="ApplicationServices" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="false" passwordFormat="Hashed" maxInvalidPasswordAttempts="5" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10" passwordStrengthRegularExpression="" applicationName="/"/&gt; </code></pre> <p>Now when I have done this, I get a null reference exception in the constructor of <code>OurBaseController</code> on this row: <code>m_info = UserInfoAccessor.GetCurrent();</code></p> <p>How come Unity doesn't inject UserInfoAccessor when I register this custom membership provider, but it works fine when I go back to the standard one?<br> Does BuildUp disturb the injection?</p> <p>I don't get any other exceptions in the debugger or in elmah.</p> <p><strong>RESOLUTION 20110726</strong></p> <p>The custom membership object got created when the UnityContainer was being set up. That made the container not being available and the exception during initialization made the UnityContainer stay uninitializad which was why the container it wasn't available.</p> <p><strong>What have I learned from this?</strong><br> Using the unity container as a resource locator is a can full of worms.</p> <p><strong>Why did I miss the error during configuration?</strong><br> When I started the site, my web browser opened a new tab. I discarded that and refreshed an earlier window. So I was looking at the result from the second request in which the site already had been started.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload