一把umbraco MVC与温莎城堡 [英] Umbraco MVC with Castle Windsor

查看:194
本文介绍了一把umbraco MVC与温莎城堡的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有没有人有获得一把umbraco MVC与温莎城堡依赖注入框架工作的示例代码?我遇到的问题是让我的面控制器使用注射parametised构造函数。我知道我做错了什么,但不知道是什么



我在这里遵循的(非一把umbraco)教程 - http://docs.castleproject.org/Windsor.Windsor-tutorial-part-four-putting-it-全together.ashx - 这基本上意味着对App_Start我运行这段代码:

  VAR集装箱=新。WindsorContainer()安装(FromAssembly.This()); 
变种的ControllerFactory =新MyCustomControllerFactory(container.Kernel);
ControllerBuilder.Current.SetControllerFactory(的ControllerFactory);



代码 MyCustomControllerFactory 如下。



另外,我执行 IWindsorInstaller 包含以下内容:

  container.Register(Classes.FromThisAssembly()
.BasedOn< SurfaceController>()
.LifestyleTransient());



我得到的例外是支持服务的成分,不Umbraco.Web.Mvc.RenderMvcController被发现,由 GetControllerInstance 方法时,我所说的表面控制器与parametised构造如下抛出:

 公共类TestSurfaceController:SurfaceController 
{
公共TestSurfaceController(INameService名称服务)
{
....
}
}

如果任何人有一些示例代码其中工程我会很感激。我已经连接好Ninject用一把umbraco,没有麻烦过,但在这个项目上我绑在温莎城堡和越来越行不通快! 。在此先感谢



MyCustomControllerFactory.cs:

 公共类MyCustomControllerFactory :DefaultControllerFactory 
{
私人只读的iKernel内核;

公共FastStartControllerFactory(内核的iKernel)
{
this.kernel =内核;
}

公共覆盖无效ReleaseController(一个IController控制器)
{
kernel.ReleaseComponent(控制器);
}

保护覆盖一个IController GetControllerInstance(RequestContext的RequestContext的,类型controllerType)
{
如果(controllerType == NULL)
{
罚球新HttpException(404的String.Format(以下简称控制器路径{0}可能不会被发现。requestContext.HttpContext.Request.Path));
}
回报(一个IController)kernel.Resolve(controllerType);
}
}


解决方案

我相信你的问题是在这里:

  ControllerBuilder.Current.SetControllerFactory(的ControllerFactory); 

这是更换控制器工厂所有控制器,包括RenderMVCController和城堡找不到该类型的匹配组件。



诀窍是使用FilteredControllerFactoryResolver,它可以让一把umbraco决定根据一些你提供的标准来使用的控制器(在此情况下,是否你的容器能够解决控制器类型)。成分并不像在一条直线MVC应用程序(恕我直言)干净,但很有效。



下面是一个(一把umbraco 7.x版)例如过滤器实现的IFilteredControllerFactory接口:

 公共类FilteredControllerFactory:的ControllerFactory,IFilteredControllerFactory 
{
公共BOOL CanHandle(RequestContext的要求)
{
型controllerType = GetControllerType(请求request.RouteData.Values [控制器]的ToString());
返回ApplicationStartup.Container.Kernel.HasComponent(controllerType);
}
}

和相应的代码来设置组成(使用< A HREF =http://our.umbraco.org/documentation/Reference/Events/application-startup> ApplicationEventHandler ):

 公共类ApplicationStartup:ApplicationEventHandler 
{
内部静态IWindsorContainer容器;

保护覆盖无效ApplicationStarting(UmbracoApplicationBase umbracoApplication,ApplicationContext中的applicationContext)
{
base.ApplicationStarting(umbracoApplication,的applicationContext);

集装箱=新WindsorContainer()
.Install(Configuration.FromAppConfig())
.Register(Classes.FromThisAssembly()支持算法FMP&下;一个IController方式>()LifestyleTransient() );

FilteredControllerFactoriesResolver.Current.InsertType&所述; FilteredControllerFactory>(0);
}
}

这方法应该工作都路由劫持和表面控制器。



最后,请注意,如果你也想支持注入API控制器,你需要单独这样组装起来。例如:

  GlobalConfiguration.Configuration.Services.Replace(typeof运算(IHttpControllerActivator),新CompositionRoot(Container.Kernel))

其中CompositionRoot是你自己的温莎组成的根类。



这里的要点 也可能证明是有用的。


Does anyone have any example code for getting Umbraco MVC working with the Castle Windsor dependency injection framework? The problem I'm having is getting my surface controllers to use injectable parametised constructors. I know I'm doing something wrong but not sure what.

I have followed the (non-Umbraco) tutorial here - http://docs.castleproject.org/Windsor.Windsor-tutorial-part-four-putting-it-all-together.ashx - which basically means on App_Start I'm running this code:

var container = new WindsorContainer().Install(FromAssembly.This());
var controllerFactory = new MyCustomControllerFactory(container.Kernel);
ControllerBuilder.Current.SetControllerFactory(controllerFactory);

Code for MyCustomControllerFactory is below.

Also, my implementation of IWindsorInstaller contains the following:

container.Register(Classes.FromThisAssembly()
    .BasedOn<SurfaceController>()
    .LifestyleTransient());

The exception I'm getting is 'No component for supporting the service Umbraco.Web.Mvc.RenderMvcController was found', thrown by the GetControllerInstance method below when I call a surface controller with a parametised constructor:

public class TestSurfaceController : SurfaceController
{
    public TestSurfaceController(INameService nameService)
    {
        ....
    }
}

If anyone has some example code which works I'd really appreciate it. I've wired up Ninject with Umbraco before with no trouble, but on this project I'm tied to Castle Windsor and getting nowhere fast! Thanks in advance.

MyCustomControllerFactory.cs:

public class MyCustomControllerFactory : DefaultControllerFactory
{
    private readonly IKernel kernel;

    public FastStartControllerFactory(IKernel kernel)
    {
        this.kernel = kernel;
    }

    public override void ReleaseController(IController controller)
    {
        kernel.ReleaseComponent(controller);
    }

    protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
    {
        if (controllerType == null)
        {
            throw new HttpException(404, string.Format("The controller for path '{0}' could not be found.", requestContext.HttpContext.Request.Path));
        }
        return (IController)kernel.Resolve(controllerType);
    }
}

解决方案

I believe your problem is here:

ControllerBuilder.Current.SetControllerFactory(controllerFactory);

This is replacing the controller factory for ALL controllers, including the RenderMVCController, and Castle can't find a matching component for that type.

The trick is to use the FilteredControllerFactoryResolver, which lets Umbraco decide which controller to use based on some criteria that you provide (in this case, whether your container can resolve the controller type). Composition is not as clean as in a straight MVC app (IMHO), but it works.

Here's an (Umbraco 7.x) example of a filtered controller that implements the IFilteredControllerFactory interface:

public class FilteredControllerFactory : ControllerFactory, IFilteredControllerFactory
{
    public bool CanHandle(RequestContext request)
    {
        Type controllerType = GetControllerType(request, request.RouteData.Values["controller"].ToString());
        return ApplicationStartup.Container.Kernel.HasComponent(controllerType);
    }
}

And the corresponding code to set up composition (using ApplicationEventHandler):

public class ApplicationStartup : ApplicationEventHandler
{
    internal static IWindsorContainer Container;

    protected override void ApplicationStarting(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
    {
        base.ApplicationStarting(umbracoApplication, applicationContext);

        Container = new WindsorContainer()
            .Install(Configuration.FromAppConfig())
            .Register(Classes.FromThisAssembly().BasedOn<IController>().LifestyleTransient());

        FilteredControllerFactoriesResolver.Current.InsertType<FilteredControllerFactory>(0);
    }
}

This approach should work both for route hijacking and for surface controllers.

Finally, note that if you also want to support injection into API controllers, you'll need to wire this up separately. For example:

GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpControllerActivator), new CompositionRoot(Container.Kernel))

where CompositionRoot is your own Windsor composition root class.

The Gist here may also prove useful.

这篇关于一把umbraco MVC与温莎城堡的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆