如何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:外部库中的控制器是否从ApiControllerinheritance?

版本控制:您的Web API项目和类库是否使用相同版本的Web API库?

如果有帮助,我可以打包我的testing解决scheme,并提供给您。 此外,作为一个注意事项,您不需要通过Web API来查找具有添加到Global.asax的行的控制器,系统会自动find控制器,让它们引用它们。

它应该按原样工作。 清单

  • inheritanceApiController
  • 结束控制器名称与控制器 。 例如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