Routes 如何让Web API/Castle Windsor识别控制器?
我找到了占位符“家庭控制器”被调用的原因 我注释掉了RouteConfig.cs中对HomeController的引用,并添加了一个我希望它调用的控制器:Routes 如何让Web API/Castle Windsor识别控制器?,routes,repository,castle-windsor,asp.net-web-api-routing,controller-factory,Routes,Repository,Castle Windsor,Asp.net Web Api Routing,Controller Factory,我找到了占位符“家庭控制器”被调用的原因 我注释掉了RouteConfig.cs中对HomeController的引用,并添加了一个我希望它调用的控制器: public class RouteConfig { public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); //If get 40
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 }
);
}
}
…但这在WindsorController工厂给了我一个空值:
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);
}
…即使部门控制器中确实存在GetCountOfDepartRecords():
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());
}
}
这是不是“太好了”
更新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接口)
而这个,
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(Classes.FromThisAssembly()
.BasedOn(typeof(ISomethingProvider))
.WithServiceAllInterfaces());
container.AddFacility<TypedFactoryFacility>();
container.Register(Component.For<IMyFirstFactory>().AsFactory());
}
…使用上面的内容(存储库)
我把断点都放进去了,它们都被击中了,然后被击中了,顺序与上面显示的相反。所以我不知道是否只允许对container.Register()进行一次调用,或者为什么我得到一个空控制器
更新4
基于Summit Dishpanhands的示例,我注释掉了RepositoriesInstaller中的代码,并将其替换为以下代码:
container.Register(
Component.For<IDepartmentRepository>().ImplementedBy<DepartmentRepository>()
);
……为此:
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;
}
…我似乎走得更远了。现在,我得到的不是运行时异常,而是BrowsetTime异常,即HTTP错误403.14-禁止:
我真的需要搞乱ISS吗,还是有什么别的东西可以解决这个难题
更新6
针对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'的定义,并且找不到接受'System.Web.Routing.RouteCollection'类型的第一个参数的扩展方法'MapHttpRoute'。”
更新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);
var controllerFactory=新的WindsorController工厂(container.Kernel);
ControllerBuilder.Current.SetControllerFactory(controllerFactory);
您也需要这样做(或者,如果您的项目仅使用WebApi,则需要这样做):
GlobalConfiguration.Configuration.Services.Replace(
类型(IHTTP控制器激活器),
新Windsorc控制器激活器(容器))
事实上,我两个都有:
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的生活方式(短暂的生活方式)与其他的(WebRequest的生活方式)不同
IRepository是我应该引用的东西(我不知道,它是无法解决的),还是您的自定义接口,如所有其他接口(IUserService、IAppService等)?
MapRoute
扩展用于MVC控制器,而DepartmentsController
是实现IHttpController
接口的Web API控制器(例如:ApiController
实现此接口)。您应该使用maphttroute
扩展名,如果有,您也可以使用WebApiConfig.cs
。好的,让我们来分析一下。您的意思是WindsorController Factory.GetControllerInstance中的值为空。我假设你的意思是controllerType为空
这意味着您的问题与Windsor无关,因此您可以暂时忽略Windsor配置,从而避免很多困惑。问题是您的WebApi路由设置不正确,因此WebApi无法根据您提供的路由找到合适的控制器
正如Kiran所说,看起来您实际上没有为WebApi映射任何路由,这可能就是您的问题所在
此外,WebApi不使用MVC使用的WindsorController工厂,您需要一个单独的类来实现IHttpControllerActivator(请参阅上面的Serdar文章中的示例链接)
其中,您当前具有以下内容:
var controllerFactory = new WindsorControllerFactory(container.Kernel);
ControllerBuilder.Current.SetControllerFactory(controllerFactory);
您也需要这样做(或者,如果您的项目仅使用WebApi,则需要这样做):
下面是您需要做的:
- 设置WebApi路由,以便WebApi而不是MVC处理对API的调用
- 实现IHttpControllerActivator,并向WebApi注册新的实现
- IDepartmentsRepository的Windsor注册重复,导致启动期间引发异常
- 我不得不将Global.asax.cs中的WebApiConfig.Register调用替换为对GlobalConfiguration.Configure的调用。以前我得到的是404(但这可能只是我的机器和你的机器之间的区别)
- 我删除了一些可能导致MVC框架处理WebApi路由的MapRoutes调用
routes.MapHttpRoute(
name: "Departments",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Departments", action = "GetCountOfDepartmentRecords", id = UrlParameter.Optional }
);
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 }
);
}
}
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));
}
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;
}
var controllerFactory = new WindsorControllerFactory(container.Kernel);
ControllerBuilder.Current.SetControllerFactory(controllerFactory);
GlobalConfiguration.Configuration.Services.Replace(
typeof (IHttpControllerActivator),
new WindsorControllerActivator(container));