views:

44

answers:

1

Having the code below in my Global.asax.cs and two controller (one based on a the other: MasterController) I don't seem to find how can I resolve the repository register in my WindsorContainer from the MasterController... the same applies in the HomeController and works perfectly... what am I doing wrong?

Global.asax.cs:

private IWindsorContainer _container;

protected void Application_Start()
{
    InitializeContainer();
    RegisterRoutes(RouteTable.Routes);
}

protected void Application_End()
{
    this._container.Dispose();
}

protected void Application_EndRequest()
{
    if (_container != null)
    {
        var contextManager = _container.Resolve<IContextManager>();
        contextManager.CleanupCurrent();
    }
}

private void InitializeContainer()
{
    _container = new WindsorContainer();

    ControllerBuilder.Current.SetControllerFactory(new WindsorControllerFactory(_container));

    // Register context manager.
    _container.Register(
        Component.For<IContextManager>()
        .ImplementedBy<EFContextManager>()
        .LifeStyle.Singleton
        .Parameters(
            Parameter.ForKey("connectionString").Eq(ConfigurationManager.ConnectionStrings["ProvidersConnection"].ConnectionString)
        )
    );

        //Products repository           
    _container.Register(
        Component.For<IProductRepository>()
        .ImplementedBy<ProductRepository>()
        .LifeStyle.Singleton
    );

    // Register all MVC controllers
    _container.Register(AllTypes.Of<IController>()
        .FromAssembly(Assembly.GetExecutingAssembly())
        .Configure(c => c.LifeStyle.Transient)
    );

}

Controller base:

public class MasterController : Controller
{
    private IProductRepository _productRepository;

    public ProductController(IProductRepository product)
    {
        _productRepository = product;
    }

    public ActionResult Index()
    {
       ViewData["product"] = _productRepository.FindOne(123);   
       return View();
    }
}

Controller based on MasterController:

public class ProductController : MasterController
{
    private IProductRepository _productRepository;

    public ProductController(IProductRepository product)
    {
        _productRepository = product;
    }

    public ActionResult Search(int id)
    {
       ViewData["product"] = _productRepository.FindOne(id);    
       return View();
    }
}
A: 

It is working as expected now and the ViewDatas are accessible from any controller/view.

First I created a public class where I store my Windsor container so it can be accessed from any controller:

public static class IOCcontainer
{
    public static IWindsorContainer Container { get; set; }
}

Then in my global.asax.cs I have:

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();
    RegisterRoutes(RouteTable.Routes);
    InitializeContainer();
}

private void InitializeContainer()
{
    _container = new WindsorContainer();

    // Register context manager.
    _container.Register(
        Component.For<IContextManager>()
        .ImplementedBy<EFContextManager>()
        .LifeStyle.Singleton
        .Parameters(
            Parameter.ForKey("connectionString").Eq(ConfigurationManager.ConnectionStrings["ProvidersConnection"].ConnectionString)
        )
    );

        //Products repository           
    _container.Register(
        Component.For<IProductRepository>()
        .ImplementedBy<ProductRepository>()
        .LifeStyle.Singleton
    );

    // Register all MVC controllers
    _container.Register(AllTypes.Of<IController>()
        .FromAssembly(Assembly.GetExecutingAssembly())
        .Configure(c => c.LifeStyle.Transient)
    );

    IOCcontainer.Container = _container; //set the container class with all the registrations

    ControllerBuilder.Current.SetControllerFactory(new WindsorControllerFactory(_container));
}

So now in my master controller I can use:

public class MasterController : Controller
{

    private IProductRepository g_productRepository;

    public MasterController() : this(null,null,null,null,null)
    {
    }

    public MasterController(IProductRepository productRepository)
    {
        g_productRepository = productRepository ?? IOCcontainer.Container.Resolve<IProductRepository>();
    }

    //I don't use an action here, this will make execute it for any action in any controller
    protected override void OnActionExecuting(ActionExecutingContext context)
    {   
        if (!(context.ActionDescriptor.ActionName.Equals("Index") && context.Controller.ToString().IndexOf("Home")>0)) {
        //I now can use this viewdata to populate a dropdownlist along the whole application
        ViewData["products"] = g_productRepository.GetProducts().ToList().SelectFromList(x => x.Id.ToString(), y => y.End.ToShortDateString());
        }
    }
}

Then the rest of controllers:

//will be based on MasterController
public class AboutController : MasterController 
{

}

public ActionResult Index()
{
    return View();
}

etc...

Probably not the most elegant way to do it but it will do until I find a better way or someone else brighten my mind up!

tricat