我发现为什么在这里调用占位符“Home Controller”
我在 RouteConfig.cs 中注释掉了对 HomeController 的引用,并添加了一个我希望它调用的控制器:
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);
}
...即使 GetCountOfDepartmentRecords() 确实存在于 DepartmentsController 中:
public int GetCountOfDepartmentRecords()
{
return _deptsRepository.Get();
}
那么,就设置或配置而言,我缺少什么或... ???
注意:我还尝试了没有“控制器”措辞的 RouteConfig 条目:
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<ApiController>()
.LifestylePerWebRequest());
}
}
...难道我做错了什么?
更新 2
也许我的项目中有太多实现 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<ApiController>()
.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<TypedFactoryFacility>();
container.Register(Component.For<IMyFirstFactory>().AsFactory());
}
}
2) 存储库安装程序
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()));
}
}
这是“好事多磨”吗?
更新 3
我的看法是:
public class ApiControllersInstaller : IWindsorInstaller
{
public void Install(Castle.Windsor.IWindsorContainer container, Castle.MicroKernel.SubSystems.Configuration.IConfigurationStore store)
{
container.Register(Classes.FromThisAssembly()
.BasedOn<ApiController>()
.LifestylePerWebRequest());
}
}
...应该注册所有实现 ApiController 接口的东西;因此,应该安装 DepartmentsController。
public class DepartmentsController : ApiController
(所有其他控制器也应如此,因为它们都实现了 ApiController 接口)。
虽然这个:
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(Classes.FromThisAssembly()
.BasedOn(typeof(ISomethingProvider))
.WithServiceAllInterfaces());
container.AddFacility<TypedFactoryFacility>();
container.Register(Component.For<IMyFirstFactory>().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(),或者为什么我得到一个空控制器......
更新 4
根据 Summit Dishpanhands 的示例,我注释掉了我在 RepositoriesInstaller 中的代码并将其替换为:
container.Register(
Component.For<IDepartmentRepository>().ImplementedBy<DepartmentRepository>()
);
......在Mudville仍然没有快乐,虽然......
更新 5
在此处使用 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 - 禁止:
我真的需要搞乱国际空间站,还是有其他东西可以解决这个难题?
更新 6
回应基兰查拉:
当我像这样将其更改为 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类型的第一个参数'可以找到...... '
更新 7
谢谢你的帮助,基兰。
我确实有一个 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 中的东西注释掉;看来我的文件太多了;就好像我的壁橱里塞满了易燃物。
更新 8
对于亚当康纳利:
“我假设你的意思是 controllerType 为空。”
是的。
“您目前有以下内容:
var controllerFactory = new 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;
}
更新 9
Serdar,这似乎很有帮助,尤其是 ServiceInstaller : IWindsorInstaller 方法。
现在,我看到 IRepository 的生活方式 (LifestyleTransient) 与其他人 (LifestylePerWebRequest) 不同。
IRepository 是我应该参考的东西(我没有,它是无法解析的),还是你的自定义接口,例如所有其余的似乎都是(IUserService、IAppService 等)?