2

I have asp.net mvc application and im using Unity as IoC container. The UnityWebActivator class has PreApplicationStartMethod which registers all the types with Unity container.

I want to register a singleton instance of a class whose property values are coming from the database.

[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(Web.App_Start.UnityWebActivator), "Start")]
[assembly: WebActivatorEx.ApplicationShutdownMethod(typeof(Web.App_Start.UnityWebActivator), "Shutdown")]
namespace Web.App_Start
{

    public static class UnityWebActivator
    {

        public static void Start()
        {
            var container = UnityConfig.GetConfiguredContainer();

            FilterProviders.Providers.Remove(FilterProviders.Providers.OfType<FilterAttributeFilterProvider>().First());
            FilterProviders.Providers.Add(new UnityFilterAttributeFilterProvider(container));

            DependencyResolver.SetResolver(new UnityDependencyResolver(container));

            Microsoft.Web.Infrastructure.DynamicModuleHelper.DynamicModuleUtility.RegisterModule(typeof(UnityPerRequestHttpModule));

            // Web API
            //GlobalConfiguration.Configuration.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(container);
        }
    }
}

and UnityConfig.cs i register all the types

public class UnityConfig
{
    #region Unity Container
    private static Lazy<IUnityContainer> container = new Lazy<IUnityContainer>(() =>
    {
        var container = new UnityContainer();
        RegisterTypes(container);
        return container;
    });

    public static IUnityContainer GetConfiguredContainer()
    {
        return container.Value;
    }

    public static void RegisterTypes(IUnityContainer container)
    {                
        container.RegisterType<DbContext, MyEntities>(new PerRequestLifetimeManager(), new InjectionFactory(x => new MyEntities()));                   

        //register singleton
        container.RegisterInstance<ApplicationSettings>(LoadApplicationSettings(container), new ContainerControlledLifetimeManager());
    }

    private static ApplicationSettings LoadApplicationSettings(IUnityContainer container)
    {
        var appSettings = new ApplicationSettings();
        using (var dbContext = new MyEntities())
        { 
            var settings = dbContext.Settings.ToList();             
            // populate appsettings from settings               
        }
    }
}

The LoadApplicationSettings method above needs to get the data from the database and create the instance of ApplicationSettings class.

However LoadApplicationSettings gets invoked as PreApplicationStartMethod which is before application_start method and since DbContext is not mapped yet i get error

InvalidOperationException: Unable to determine application context. The ASP.NET application path could not be resolved.

and:   

InvalidOperationException: This method cannot be called during the application's pre-start initialization stage.

So as per the suggestion here i did two things:

1> Remove the line [assembly: WebActivator.PreApplicationStartMethod]
2> Add a call to the UnityWebActivator.Start() method in the Application_Start() event of the global asax.

However doing so causes another error when registering UnityPerRequestHttpModule

    public static void Start()
    {
        // removed code for brevity

        // get error at line below
        Microsoft.Web.Infrastructure.DynamicModuleHelper.DynamicModuleUtility.RegisterModule(typeof(UnityPerRequestHttpModule));

        //removed code for brevity
    }

"Cannot register a module after the application has been initialized."}

LP13
  • 25,900
  • 45
  • 172
  • 339

1 Answers1

0

You can register ApplicationSettings using an InjectionConstructor. This will defer creation (and the loading of the settings from the database) until the first time they are resolved from the container. Presumably this should be after the application has finished bootstrapping.

Here is the new registration:

//register singleton
container.RegisterType<ApplicationSettings>(
    new ContainerControlledLifetimeManager(), 
    new InjectionFactory(c => LoadApplicationSettings(c)));
Randy Levy
  • 22,412
  • 4
  • 67
  • 93