Umbraco MVC与温莎城堡

有没有人有任何示例代码让Umbraco MVC使用Castle Windsordependency injection框架? 我遇到的问题是让我的表面控制器使用可注射的参数化构造函数。 我知道我做错了什么但不确定是什么。

我在这里遵循了(非Umbraco)教程 – http://docs.castleproject.org/Windsor.Windsor-tutorial-part-four-putting-it-all-together.ashx – 这基本上意味着在App_Start上我是运行此代码:

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

MyCustomControllerFactory代码如下。

此外,我的IWindsorInstaller实现包含以下内容:

 container.Register(Classes.FromThisAssembly() .BasedOn() .LifestyleTransient()); 

我得到的例外是’找不到支持服务的组件Umbraco.Web.Mvc.RenderMvcController’,当我用一个参数化构造函数调用一个表面控制器时,由下面的GetControllerInstance方法抛出:

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

如果有人有一些有效的示例代码,我真的很感激。 我之前已经把Ninject和Umbraco连接起来没有遇到任何麻烦,但是在这个项目中,我被绑在温莎城堡上并且无处可去! 提前致谢。

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); } } 

我相信你的问题在这里:

 ControllerBuilder.Current.SetControllerFactory(controllerFactory); 

这将替换所有控制器的控制器工厂,包括RenderMVCController,而Castle无法找到该类型的匹配组件。

诀窍是使用FilteredControllerFactoryResolver,它允许Umbraco根据您提供的某些条件决定使用哪个控制器(在这种情况下,您的容器是否可以解析控制器类型)。 组合不像直接MVC应用程序(恕我直言)那样干净,但它的工作原理。

这是一个实现IFilteredControllerFactory接口的过滤控制器的(Umbraco 7.x)示例:

 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); } } 

和相应的代码来设置组合(使用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().LifestyleTransient()); FilteredControllerFactoriesResolver.Current.InsertType(0); } } 

这种方法既适用于路线劫持,也适用于地面控制器。

最后,请注意,如果您还想支持注入API控制器,则需要单独进行连接。 例如:

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

其中CompositionRoot是您自己的Windsor组合根类。

这里的要点也可能有用。

我已经阅读了Kristopher的答案,我发现它很有趣,因为我不知道IFilteredControllerFactory及其用途。 感谢分享。

无论如何,通常在我的项目中我有很多dll包含每个自己的控制器,所以我更喜欢以更一般的方式注册所有控制器:

 container.Register( Classes .FromAssemblyInDirectory(new AssemblyFilter(AssemblyDirectory)) .BasedOn() .LifestyleTransient()); 

哪里

  ///  /// Local Directory where are present all the assemblies ///  static public string AssemblyDirectory { //Snippet code from: https://gist.github.com/iamkoch/2344638 get { var codeBase = Assembly.GetExecutingAssembly().CodeBase; var uri = new UriBuilder(codeBase); var path = Uri.UnescapeDataString(uri.Path); return Path.GetDirectoryName(path); } } 

通过这种方式,Umbraco的RenderMVCController也将被映射并正确解析。

最近我在Umbraco应用程序中写了几篇关于DI的文章:

  • MVC控制器工厂
  • MVCfilter中的属性注入

希望它可以提供帮助