如何configurationWeb Api 2在单独的项目中查找控制器? (就像我在Web Api中所做的那样)
我曾经把我的控制器放到Mvc Web Api中的一个单独的类库项目中。 我曾经在我的web api项目的global.asax中添加以下行来查找单独项目中的控制器:
ControllerBuilder.Current.DefaultNamespaces.Add("MyClassLibraryProject.Controllers");
除了添加上面的行之外,我从来不需要做任何其他configuration。 这对我来说一直很好。
但是我无法使用上面的方法在WebApi2中执行相同的操作。 它只是不起作用。 WebApi2项目仍然尝试在自己的项目的控制器文件夹中find控制器。
– 在2个月后给予小小的摘要更新(当我开始赏金时):
我创build了一个WebApiOne解决scheme,它有两个项目,第一个是WebApi项目,第二个是控制器类库。 如果我将控制器类库项目的引用添加到WebApi项目中,则所有工作均按预期工作。 即如果我去http://mydevdomain.com/api/values我可以看到正确的输出。
我现在创build了第二个名为WebApiTwo的项目,它有两个项目,第一个是WebApi2项目,第二个是控制器类库。 如果我将控制器类库项目的引用添加到WebApi2项目,它不会按预期工作。 即如果我去http://mydevdomain.com/api/values我得到“没有findtypes匹配名为”价值观“的控制器。
对于第一个项目我没有做任何自定义设置,我没有:
ControllerBuilder.Current.DefaultNamespaces.Add("MyClassLibraryProject.Controllers");
在我的global.asax中,我还没有在他的两篇博文中实现StrathWeb提出的任何定制解决scheme,因为我认为它不再适用。 因为所有的工作只是通过将控制器项目的引用添加到WebApi项目中。
所以我希望所有的工作都一样的WebApi2 …但它不是。 有没有人真的想在WebAPi2中做这个?
我刚刚证实,这工作正常。 检查事项:
参考:您的主要Web API项目是否引用外部类库?
路由:您是否设置了可能会干扰外部控制器的路由?
保护级别:外部库中的控制器是否public
?
inheritance:外部库中的控制器是否从ApiController
inheritance?
版本控制:您的Web API项目和类库是否使用相同版本的Web API库?
如果有帮助,我可以打包我的testing解决scheme,并提供给您。 此外,作为一个注意事项,您不需要通过Web API来查找具有添加到Global.asax
的行的控制器,系统会自动find控制器,让它们引用它们。
它应该按原样工作。 清单
- inheritance
ApiController
- 结束控制器名称与控制器 。 例如
ValuesController
- 确保WebApi项目和类库项目引用相同的WebApi程序集
- 尝试使用属性路由强制路由
-
Clean
解决scheme,手动删除文件夹并重build - 删除
Temporary ASP.NET Files
夹。 WebApi和MVCcaching控制器查找结果 - 调用`config.MapHttpAttributeRoutes(); 确保框架考虑属性路由
- 确保你正在调用的方法是处理正确的HTTP动词(如果它是一个GETnetworking方法,你可以通过浏览器URL调用,如果是POST,你必须另外制作一个Web请求)
这个控制器:
[RoutePrefix("MyValues")] public class AbcController : ApiController { [HttpGet] [Route("Get")] public string Get() { return "Ok!"; } }
匹配这个url:
http://localhost/MyValues/Get
(注意路由中没有/api/
,因为它没有在RoutePrefix
指定。
控制器查找caching: 这是默认的控制器parsing器 。 您将在源代码中看到它caching查找结果。
/// <summary> /// Returns a list of controllers available for the application. /// </summary> /// <returns>An <see cref="ICollection{Type}" /> of controllers.</returns> public override ICollection<Type> GetControllerTypes(IAssembliesResolver assembliesResolver) { HttpControllerTypeCacheSerializer serializer = new HttpControllerTypeCacheSerializer(); // First, try reading from the cache on disk List<Type> matchingTypes = ReadTypesFromCache(TypeCacheName, IsControllerTypePredicate, serializer); if (matchingTypes != null) { return matchingTypes; } ... }
遇到同样的情况,@ justmara把我放在正确的道路上。 下面是如何完成从@ justmara的答案依赖程序集的力加载:
1)重写DefaultAssembliesResolver类
public class MyNewAssembliesResolver : DefaultAssembliesResolver { public virtual ICollection<Assembly> GetAssemblies() { ICollection<Assembly> baseAssemblies = base.GetAssemblies(); List<Assembly> assemblies = new List<Assembly>(baseAssemblies); var controllersAssembly = Assembly.LoadFrom(@"Path_to_Controller_DLL"); baseAssemblies.Add(controllersAssembly); return baseAssemblies; } }
2)在configuration部分,将默认值replace为新的实现
config.Services.Replace(typeof(IAssembliesResolver), new MyNewAssembliesResolver());
我用这个博客的指针拼凑了这个语法:
http://www.strathweb.com/2013/08/customizing-controller-discovery-in-asp-net-web-api/
正如其他人所说的,如果您强制直接引用控制器加载,则会知道是否遇到此问题。 另一种方法是示例CurrentDomain.GetAssemblies()
的结果,看看你的程序集是否在列表中。
另外:如果您使用OWIN组件进行自我托pipe,您将遇到此问题。 在testing时请记住,DefaultAssembliesResolver不会在第一个WebAPI请求提交之前开始(我花了一段时间才意识到这一点)。
你确定你的引用程序集加载之前调用IAssembliesResolver服务? 尝试在您的应用程序中插入一些虚拟代码,如
var a = new MyClassLibraryProject.Controllers.MyClass();
在configuration方法中(但是不要忘记,如果从不使用“a”,那么编译器可以“优化”这个代码并完全移除它)。 我有类似的问题与程序集加载顺序。 在启动时结束与力加载相关的组件。
你需要告诉webapi / mvc加载你的引用程序集。 你可以使用web.config中的编译/程序集部分。
<compilation debug="true" targetFramework="4.5.2"> <assemblies> <add assembly="XYZ.SomeAssembly" /> </assemblies> </compilation>
就那么简单。 你可以用@ user1821052build议的方式用代码来完成,但是这个web.config版本会有相同的效果。
除了已经说过的话:
确保在不同的命名空间中没有两个同名的控制器。
刚刚有一个控制器(foo.UserApiController)应部分迁移到一个新的名称空间(bar.UserApiController)和URI的情况。 旧的控制器按照惯例映射到/ userapi,新的控制器通过RoutePrefix["api/users"]
进行属性路由。 新的控制器没有工作,直到我把它重命名为bar.UserFooApiController。
当使用AttributeRouting时,使用Route
属性来装饰你的方法是很容易被遗忘的,特别是当你在控制器类上使用RoutePrefix
属性的时候。 看起来你的控制器组装没有被web APIpipe道拾取。
如果您的类库是使用EF
构build的,那么请确保在类库项目的App.config
指定了连接string, 并在Web.config
为您的Web API MVC
项目指定了AND 。