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

2

6

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?

Kristikristian answered 12/10, 2011 at 3:8 Comment(0)
S
9

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.

Silage answered 15/10, 2011 at 19:21 Comment(4)
wait, so I have to then manually setup any dependancies of SomeHelper to then right?Kristikristian
@Blankman, dependency injection works in controllers because you have used a custom controller provider factory which uses windsor to inject those dependencies. As far as your second question about the dependencies of the SomeHelper is concerned, you do not need to manually setup them. You setup those dependencies the same way you would as if it was a controller dependency. When you use .Resolve<ISomeHelper>() this will automatically provide registered dependencies.Silage
ok so I was right about that the viewpage is instantiated outside of the scope of the controller? Seems odd though, I would have assumed the webviewpage would be created by the controller and thus doesn't need to be manually wired up like this.Kristikristian
It works out of the box with Autofac if you feel like "upgrading" - code.google.com/p/autofac/wiki/MvcIntegration3Impugn
A
0

I think what you'll want to do is hook in to MVC3's Service Location to control how view pages are created. I haven't used MVC3 yet, but I found an article that describes the Service Location feature and that may give you the "hook" you need to be able to access the WebViewPage before it's processed.

By getting access to the WebViewPage before it's processed, you can use Windsor to do property injection of your view page. By default, Windsor only does constructor injection, but you can find a sample of doing property injection via an extension method on a blog post I did a couple of years ago on MVC1 ActionFilters.

Alainaalaine answered 13/10, 2011 at 13:31 Comment(1)
mine is doing property injection just fine, not sure what I did but it is workign with that.Kristikristian

© 2022 - 2024 — McMap. All rights reserved.