为了模块化,我在不同的程序集中创建了一些控制器.每个程序集代表整个系统的有界上下文(模块,子系统,分区等).
每个模块的控制器都是由对其他模块一无所知的人开发的,中央协调器即将在一个应用程序中覆盖所有这些模块.
所以,有一个名为school的模块,它有一个TeacherController.它的输出是Contoso.School.UserService.dll.
主要的协调器被调用Education,它有一个引用Contoso.School.UserService.dll.
我program.cs是:
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args).UseKestrel()
.UseStartup<Startup>()
.Build();
Run Code Online (Sandbox Code Playgroud)
然而对于教师控制器的路线,我得到404.如何在其他组件中使用控制器?
我正在尝试创建这样的通用控制器:
[Route("api/[controller]")]
public class OrdersController<T> : Controller where T : IOrder
{
[HttpPost("{orderType}")]
public async Task<IActionResult> Create(
[FromBody] Order<T> order)
{
//....
}
}
Run Code Online (Sandbox Code Playgroud)
我打算使用{orderType} URI段变量来控制控制器的泛型类型.我正在尝试自定义IControllerFactory和IControllerActivator,但没有任何工作.每次我尝试发送请求时,都会收到404响应.我的自定义控制器工厂(和激活器)的代码永远不会执行.
显然问题是ASP.NET Core期望有效的控制器以后缀"Controller"结束,但我的通用控制器却具有(基于反射的)后缀"Controller`1".因此,它声明的基于属性的路线将被忽视.
在ASP.NET MVC中,至少在早期,它DefaultControllerFactory负责发现所有可用的控制器.它测试了"Controller"后缀:
MVC框架提供了一个默认的控制器工厂(恰当地命名为DefaultControllerFactory),它将搜索appdomain中的所有程序集,查找实现IController的所有类型,其名称以"Controller"结尾.
显然,在ASP.NET Core中,控制器工厂不再负有此责任.正如我之前所说,我的自定义控制器工厂为"普通"控制器执行,但从不为通用控制器调用.因此,在评估过程的早期还有其他一些东西可以控制控制器的发现.
有谁知道什么"服务"界面负责该发现?我不知道自定义界面或"钩子"点.
有没有人知道如何让ASP.NET Core"转储"它发现的所有控制器的名称?编写单元测试可以很好地验证我期望的任何自定义控制器发现确实有效.
顺便提一下,如果存在允许发现通用控制器名称的"钩子",则意味着还必须规范路由替换:
[Route("api/[controller]")]
public class OrdersController<T> : Controller { }
Run Code Online (Sandbox Code Playgroud)
无论给出什么值T,[controller]名称必须保持简单的基本通用名称.使用上面的代码作为示例,[controller]值将是"Orders".它不会是"Orders`1"或"OrdersOfSomething".
这个问题也可以通过显式声明封闭泛型类型来解决,而不是在运行时生成它们:
public class VanityOrdersController : OrdersController<Vanity> { }
public class ExistingOrdersController : OrdersController<Existing> { }
Run Code Online (Sandbox Code Playgroud)
上面的工作,但它产生我不喜欢的URI路径:
~/api/VanityOrders
~/api/ExistingOrders
Run Code Online (Sandbox Code Playgroud)
我真正想要的是这个:
~/api/Orders/Vanity
~/api/Orders/Existing
Run Code Online (Sandbox Code Playgroud)
另一个调整让我得到我正在寻找的URI:
[Route("api/Orders/Vanity", …Run Code Online (Sandbox Code Playgroud) 在 WebApi 中,您可以替换内置的IHttpControllerTypeResolver,其中您可以以任何您喜欢的方式找到您想要的 Api 控制器。
在使用 MVC 的 AspNetCore 中,PartsManager 和 FeatureManager 存在令人困惑的混乱,其中某些地方与控制器有关。我能找到的所有文档和讨论似乎都假设您是一名从事 MVC 本身的开发人员,并且您已经了解 ApplicationPartManager 和 ControllerFeatureProvider 之间的区别,而无需解释任何内容。
在最简单的示例中,我特别想做的是启动 AspNetCore 2.0 Kestrel 服务器的实例,并让它仅解析预配置的硬编码单个控制器。我明确地不希望它做正常的发现之类的事情。
在 WebApi 中,您只需执行以下操作:
public class SingleControllerTypeResolver : IHttpControllerTypeResolver
{
readonly Type m_type;
public SingleControllerTypeResolver(Type type) => m_type = type;
public ICollection<Type> GetControllerTypes(IAssembliesResolver assembliesResolver) => new[] { m_type };
}
// ...
// in the configuration:
config.Services.Replace(typeof(IHttpControllerTypeResolver), new SingleControllerTypeResolver(typeof(MySpecialController)))
Run Code Online (Sandbox Code Playgroud)
但是我一直试图使用 aspnetcore 2 获得等效的结果