我发现了为什么占位符“ Home Controller”在这里被调用
我在RouteConfig.cs中注释掉了对HomeController的引用,并添加了一个我希望它调用的Controller:
public class RouteConfig { public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); //If get 404 error re: favicon, see http://docs.castleproject.org/(X(1)S(vv4c5o450lhlzb45p5wzrq45))/Windsor.Windsor-tutorial-part-two-plugging-Windsor-in.ashx or just uncomment the line below: //routes.IgnoreRoute("{*favicon}", new { favicon = @"(.*/)?favicon.ico(/.*)?" }); //routes.MapRoute( // name: "Default", // url: "{controller}/{action}/{id}", // defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } //); routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "DepartmentsController", action = "GetCountOfDepartmentRecords", id = UrlParameter.Optional } ); } }
...但这在WindsorControllerFactory中为我提供了一个空值:
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); }
...即使在DepartmentsController中确实存在GetCountOfDepartmentRecords(),也是如此:
public int GetCountOfDepartmentRecords() { return _deptsRepository.Get(); }
那么,我在设置或配置方面还是缺少什么?
注意:我还尝试过RouteConfig条目,而没有“ Controller”字样:
defaults: new { controller = "Departments", action = "GetCountOfDepartmentRecords", id = UrlParameter.Optional }
...但是没关系。
这是我在WindsorDependencyResolver中具有的功能:
public class ApiControllersInstaller : IWindsorInstaller { public void Install(Castle.Windsor.IWindsorContainer container, Castle.MicroKernel.SubSystems.Configuration.IConfigurationStore store) { container.Register(Classes.FromThisAssembly() .BasedOn() .LifestylePerWebRequest()); } }
...难道我做错了什么?
也许我的项目中有太多实现IWindsorInstaller的类?
&& ||,相关地,我在太多地方/太多地方叫container.Register()?
我在三个地方调用了container.Register():
0)WindsorDependencyResolver.cs:
public class ApiControllersInstaller : IWindsorInstaller { public void Install(Castle.Windsor.IWindsorContainer container, Castle.MicroKernel.SubSystems.Configuration.IConfigurationStore store) { container.Register(Classes.FromThisAssembly() .BasedOn() .LifestylePerWebRequest()); } }
1)SomethingProviderInstaller.cs:
public class SomethingProviderInstaller : IWindsorInstaller { public void Install(IWindsorContainer container, IConfigurationStore store) { container.Register(Classes.FromThisAssembly() .BasedOn(typeof(ISomethingProvider)) .WithServiceAllInterfaces()); container.AddFacility(); container.Register(Component.For ().AsFactory()); } }
2)RepositoriesInstaller
public class RepositoriesInstaller : IWindsorInstaller { public void Install(IWindsorContainer container, IConfigurationStore store) { container.Register( Types.FromThisAssembly() .Where(type => type.Name.EndsWith("Repository")) .WithService.DefaultInterfaces() .Configure(c => c.LifestylePerWebRequest())); } }
这是“一件好事”吗?
我的看法是:
public class ApiControllersInstaller : IWindsorInstaller { public void Install(Castle.Windsor.IWindsorContainer container, Castle.MicroKernel.SubSystems.Configuration.IConfigurationStore store) { container.Register(Classes.FromThisAssembly() .BasedOn() .LifestylePerWebRequest()); } }
...应该注册实现ApiController接口的所有内容;因此,应该安装DepartmentsController。
public class DepartmentsController : ApiController
(所有其他Controller都应该这样做,因为它们都实现了ApiController接口)。
而这个:
public void Install(IWindsorContainer container, IConfigurationStore store) { container.Register(Classes.FromThisAssembly() .BasedOn(typeof(ISomethingProvider)) .WithServiceAllInterfaces()); container.AddFacility(); container.Register(Component.For ().AsFactory()); }
...只会注册实现ISomethingProvider的单个类。
最后是这个:
container.Register(Types.FromThisAssembly().Where(type => type.Name.EndsWith(“ Controllers”)).WithService.DefaultInterfaces().Configure(c => c.LifestylePerWebRequest()));
...将注册名为Controller的所有内容。
注意:我更换了:
.Where(type => type.Name.EndsWith("Repository"))
...以及上面的内容(存储库)。
我把断点都放在了它们中,然后它们都被击中,然后被击中,其顺序与上面显示的顺序相反。所以我不知道是否只允许一个对container.Register()的调用,或者为什么我得到一个空的Controller ...
基于示例这里通过峰会Dishpanhands,我注释掉的代码我在RepositoriesInstaller以及与此替代它:
container.Register( Component.For().ImplementedBy () );
尽管在Mudville仍然没有喜悦
在此处使用Summit的代码[ 使用Castle Windsor的WebAPI中的依赖注入,我将Global.asax.cs中的代码更改为:
protected void Application_Start() { AreaRegistration.RegisterAllAreas(); GlobalConfiguration.Configure(WebApiConfig.Register); BootstrapContainer(); } private static void BootstrapContainer() { _container = new WindsorContainer().Install(FromAssembly.This()); var controllerFactory = new WindsorControllerFactory(_container.Kernel); ControllerBuilder.Current.SetControllerFactory(controllerFactory); GlobalConfiguration.Configuration.Services.Replace( typeof(IHttpControllerActivator), new WindsorCompositionRoot(_container)); }
...对此:
protected void Application_Start() { AreaRegistration.RegisterAllAreas(); WebApiConfig.Register(GlobalConfiguration.Configuration); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); RouteConfig.RegisterRoutes(RouteTable.Routes); BundleConfig.RegisterBundles(BundleTable.Bundles); ConfigureWindsor(GlobalConfiguration.Configuration); } public static void ConfigureWindsor(HttpConfiguration configuration) { _container = new WindsorContainer(); _container.Install(FromAssembly.This()); _container.Kernel.Resolver.AddSubResolver(new CollectionResolver(_container.Kernel, true)); var dependencyResolver = new WindsorDependencyResolver(_container); configuration.DependencyResolver = dependencyResolver; }
...而且我似乎已经走得更远了。现在,我得到了一个浏览时间异常,而不是运行时异常,即HTTP错误403.14-禁止:
我真的需要搞砸国际空间站吗,还是有其他方法可以解决这个难题?
针对Kiran Challa:
当我将其更改为MapHttpRoute时,如下所示:
routes.MapHttpRoute( name: "Departments", url: "{controller}/{action}/{id}", defaults: new { controller = "Departments", action = "GetCountOfDepartmentRecords", id = UrlParameter.Optional } );
...我收到编译时错误“ 'System.Web.Routing.RouteCollection'不包含'MapHttpRoute'的定义,并且没有扩展方法'MapHttpRoute'接受类型为'System.Web.Routing.RouteCollection的第一个参数可以找到... ”
谢谢你的帮助,基兰。
我确实有一个WebApiConfig.cs,它实际上已经拥有所有这些:
public static class WebApiConfig { public static void Register(HttpConfiguration config) { // Web API configuration and services // Web API routes config.MapHttpAttributeRoutes(); config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); config.Routes.MapHttpRoute( name: "DefaultApiWithParameters", routeTemplate: "api/{controller}/{ID}/{CountToFetch}" //defaults: new { ID = RouteParameter.Optional, CountToFetch = RouteParameter.Optional } ); config.Routes.MapHttpRoute( name: "DefaultApiWith3Parameters", routeTemplate: "api/{controller}/{ID}/{packSize}/{CountToFetch}" //defaults: new { ID = RouteParameter.Optional, packSize = RouteParameter.Optional, CountToFetch = RouteParameter.Optional } ); } }
...所以我想我应该只注释掉RouteConfig.cs中的内容;似乎我的文件太多了;好像我的衣柜里塞满了易燃物品。
对于亚当·康纳利:
“我假设您的意思是controllerType为null。”
是。
“目前您有类似以下内容的地方:
var controllerFactory =新的WindsorControllerFactory(container.Kernel); ControllerBuilder.Current.SetControllerFactory(controllerFactory); 您还需要执行以下操作(或者,如果您的项目仅使用WebApi,则执行以下操作):
GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpControllerActivator),new WindsorControllerActivator(container));“
实际上,我确实有两个:
private static void BootstrapContainer() { _container = new WindsorContainer().Install(FromAssembly.This()); var controllerFactory = new WindsorControllerFactory(_container.Kernel); ControllerBuilder.Current.SetControllerFactory(controllerFactory); GlobalConfiguration.Configuration.Services.Replace( typeof(IHttpControllerActivator), new WindsorCompositionRoot(_container)); }
...但目前未调用BootstrapContainer(),因此均未调用。替代的是:
private static IWindsorContainer _container; . . . protected void Application_Start() { AreaRegistration.RegisterAllAreas(); WebApiConfig.Register(GlobalConfiguration.Configuration); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); RouteConfig.RegisterRoutes(RouteTable.Routes); BundleConfig.RegisterBundles(BundleTable.Bundles); ConfigureWindsor(GlobalConfiguration.Configuration); } public static void ConfigureWindsor(HttpConfiguration configuration) { _container = new WindsorContainer(); _container.Install(FromAssembly.This()); _container.Kernel.Resolver.AddSubResolver(new CollectionResolver(_container.Kernel, true)); var dependencyResolver = new WindsorDependencyResolver(_container); configuration.DependencyResolver = dependencyResolver; }
Serdar,这似乎很有帮助,尤其是ServiceInstaller:IWindsorInstaller方法。
现在,我看到IRepository具有与其他生活方式(LifestylePerWebRequest)不同的生活方式(LifestyleTransient)。
IRepository是我应该参考的东西(我不是,它无法解决),还是您自己的自定义接口,例如其余所有接口(IUserService,IAppService等)?
好的,让我们分解一下。您说的是WindsorControllerFactory.GetControllerInstance中的值为空。我假设您的意思是controllerType为null。
这意味着您的问题与Windsor无关,因此,通过暂时忽略您的Windsor配置,可以避免很多混乱。问题是您的WebApi路由设置不正确,因此WebApi无法根据您提供的路由找到合适的控制器。
就像Kiran所说的,看起来您实际上没有为WebApi映射任何路由,这可能是您的问题所在。
另外,WebApi不使用MVC使用的WindsorControllerFactory,您需要一个单独的类来实现IHttpControllerActivator(有关示例的链接,请参见上面的Serdar文章)。
您当前所在的位置如下所示:
var controllerFactory = new WindsorControllerFactory(container.Kernel); ControllerBuilder.Current.SetControllerFactory(controllerFactory);
您还需要执行以下操作(或者,如果您的项目仅使用WebApi,则执行以下操作):
GlobalConfiguration.Configuration.Services.Replace( typeof (IHttpControllerActivator), new WindsorControllerActivator(container));
所以这是您需要做的:
设置您的WebApi路由,以便WebApi而不是MVC处理对您的API的调用。
实现IHttpControllerActivator,并向WebApi注册新的实现。
更新资料
我已经掌握了您的资料来源,并解决了一些问题。我在https://github.com/bclayshannon/WebAPICastleWindsorExtravaganza/pull/1上创建了包含其修复程序的请求请求。请看一下有关我所更改内容的详细信息。以下是我所做更改的简要摘要:
IDepartmentsRepository的Windsor注册重复,导致在启动过程中引发异常。
我必须用对GlobalConfiguration.Configure的调用替换Global.asax.cs中的WebApiConfig.Register调用。以前我得到的是404(但这可能只是我的机器和您的机器之间的区别)。
我删除了一些导致MVC框架处理WebApi路由的MapRoutes调用。
另外,我将所有API控制器都移到api文件夹中,以使内容更易于理解,并且在DepartmentsController上使用了属性路由。一个示例调用是GET / api / Departments / Count。使用属性路由不是必需的,但是通常可以使用它来创建一个体面的API。
我已经验证我现在可以发出以下请求并进入DepartmentsController:
GET / api /部门/计数
GET / api /部门?ID = 123&CountToFetch = 100