Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom base page type for my razor views, how to use castle windsor to autowire properties?

My base page looks like:

namespace ASDF.Mvc.ViewEngines.Razor
{
    public abstract class WebViewPage<TModel> : System.Web.Mvc.WebViewPage<TModel>
    {

        public ISomeHelper SomeHelper { get; set; }
    }
}

My views/web.config

<system.web.webPages.razor>
    <host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
    <pages pageBaseType="ASDF.Mvc.ViewEngines.Razor.WebViewPage">
      <namespaces>
        <add namespace="System.Web.Mvc" />
        <add namespace="System.Web.Mvc.Ajax" />
        <add namespace="System.Web.Mvc.Html" />
        <add namespace="System.Web.Routing" />
      </namespaces>
    </pages>
  </system.web.webPages.razor>

How can I have this wired up such that SomeHelper will be wired up using Castle.

This is coming back null at the moment, I have wired up ISomeHelper already and things work fine for my controllers/repositories/service classes.

I'm guessing this WebViewPage is called somewhere where my container doesn't have access to (like at the controller level).

How do I get this to work?

like image 858
Blankman Avatar asked Oct 12 '11 03:10

Blankman


1 Answers

The first thing about dependency injection into custom web pages like this is that you cannot use constructor injection. It's a pity and I hope they will improve this in future versions. The reason for that is that the actual class that implements this is dynamically emitted at runtime by the ASP.NET engine.

So we canonly use property injection at the moment.

So one possibility is to use a custom IDependencyResolver. Unfortunately IDependencyResolver doesn't play nice with Castle Windsor. Would have been a piece of cake with Ninject for example. All you would have to do is to decorate the SomeHelper property with the [Inject] attribute:

[Inject]
public ISomeHelper SomeHelper { get; set; }

and it would have been automatically wired by Ninject as it uses a custom IDependencyResolver. I am afraid that with Windsor you will have to do this manually. So you could make your container public in Global.asax and then:

public abstract class WebViewPage<TModel> : System.Web.Mvc.WebViewPage<TModel>
{
    protected WebViewPage()
    {
        SomeHelper = MvcApplication.WindsorContainer.Resolve<ISomeHelper>();
    }

    public ISomeHelper SomeHelper { get; set; }
}

I know that this sucks but I am afraid it is the harsh reality. Or maybe switch to Ninject? It plays really great with ASP.NET MVC 3 and its IDependencyResolver.

like image 139
Darin Dimitrov Avatar answered Sep 29 '22 13:09

Darin Dimitrov