gpt4 book ai didi

routes - 如何获取Web API/CaSTLe Windsor来识别 Controller ?

转载 作者:行者123 更新时间:2023-12-01 15:21:39 25 4
gpt4 key购买 nike

我发现了为什么占位符“Home Controller”被称为here

我在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<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)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()));
}
}

这是“太好了”吗?

更新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

(所有其他Controller都应该这样做,因为它们都实现了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()的调用,或者为什么我得到一个空的Controller ...

更新4

基于Summit Dishpanhands的 here示例,我注释掉了RepositoriesInstaller中的代码,并用以下代码替换了它:
container.Register(
Component.For<IDepartmentRepository>().ImplementedBy<DepartmentRepository>()
);

尽管在Mudville仍然没有喜悦

更新5

在此处使用Summit的代码[ Dependency Injection in WebAPI with Castle Windsor,我从以下位置将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

针对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的第一个参数'可以找到...”

更新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为null。”

是。

“目前您拥有类似以下内容的地方:

var controllerFactory =新的WindsorControllerFactory(container.Kernel);
ControllerBuilder.Current.SetControllerFactory(controllerFactory);
您还需要执行以下操作(或者,如果您的项目仅使用WebApi,则执行以下操作):

GlobalConfiguration.Configuration.Services.Replace(
typeof(IHttpControllerActivator),
新的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, this似乎非常有用,尤其是ServiceInstaller:IWindsorInstaller方法。

现在,我看到IRepository具有与其他生活方式(LifestylePerWebRequest)不同的生活方式(LifestyleTransient)。

IRepository是我应该参考的东西(我不是,它无法解决),还是它是您自己的自定义接口,例如所有其他接口似乎都是(IUserService,IAppService等)?

最佳答案

好的,让我们分解一下。您说的是在WindsorControllerFactory.GetControllerInstance中获得null。我假设您的意思是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中创建了包含其修复程序的请求请求。看一看,了解我所做更改的详细信息。以下是我所做更改的简要摘要:
  • IDspartmentsRepository的Windsor注册重复,导致在启动期间引发异常。
  • 我必须将Global.asax.cs中的WebApiConfig.Register调用替换为对GlobalConfiguration.Configure的调用。以前我得到的是404(但这可能只是我的机器和您的机器之间的区别)。
  • 我删除了一些导致MVC框架处理WebApi路由的MapRoutes调用。

  • 此外,我将所有API控制器都移到api文件夹中,以使内容更易于理解,并且在DepartmentsController上使用了属性路由。一个示例调用是GET / api / Departments / Count。
    使用属性路由不是必需的,但是通常可以使用它来创建一个体面的API。

    我已验证自己现在可以发出以下请求并进入DepartmentsController:
  • GET / api /部门/计数
  • GET / api / Departments?ID = 123&CountToFetch = 100
  • 关于routes - 如何获取Web API/CaSTLe Windsor来识别 Controller ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20960690/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com