如何配置Web Api 2寻找控制器在一个单独的项目?(就像我过去在Web Api中所做的那样)
本文关键字:Api Web 项目 过去 配置 何配置 寻找 控制器 一个 单独 | 更新日期: 2023-09-27 17:51:00
我曾经把我的控制器放在Mvc Web Api的一个单独的类库项目中。我过去常常在我的web api项目的全局文件中添加以下代码行。在单独的项目中查找控制器:
ControllerBuilder.Current.DefaultNamespaces.Add("MyClassLibraryProject.Controllers");
我从来没有做过任何其他配置,除了添加上面的行。这对我来说一直很有效。
然而,我无法使用上述方法在WebApi2中做同样的事情。这根本行不通。WebApi2项目仍然尝试在它自己的项目的controllers文件夹中找到控制器。
—在2个月后给出一些总结更新(当我开始赏金时):
我已经创建了一个WebApiOne解决方案,它有2个项目,第一个是WebApi项目,第二个是控制器类库。如果我将对控制器类库项目的引用添加到WebApi项目中,一切都如预期的那样工作。例如,如果我去http://mydevdomain.com/api/values,我可以看到正确的输出。
我现在已经创建了第二个名为webapittwo的项目,它有2个项目,第一个是WebApi2项目,第二个是控制器类库。如果我将控制器类库项目的引用添加到WebApi2项目,它不会像预期的那样工作。即,如果我去http://mydevdomain.com/api/values我得到"没有类型被发现,匹配的控制器名为'值'。"
对于第一个项目,我根本没有做任何自定义设置,我没有:
ControllerBuilder.Current.DefaultNamespaces.Add("MyClassLibraryProject.Controllers");
在我的全局。asax,我没有实现StrathWeb在他的两篇博客文章中提出的任何自定义解决方案,因为我认为它不再适用;因为只要把控制器项目的引用添加到WebApi项目中就可以了。
所以我希望所有的工作相同的WebApi2…但事实并非如此。有没有人真的尝试过在WebAPi2中这样做?
我刚刚确认这很好。检查事项:
References:你的主Web API项目引用外部类库吗?
Routing:是否设置了可能干扰外部控制器的路由?
保护级别:控制器是否在外部库public
?
Inheritance: Do the controllers in the external library from ApiController
?
Versioning:你的Web API项目和类库都使用相同版本的Web API库吗?
如果有帮助的话,我可以把我的测试解决方案打包给你。另外,需要注意的是,您不需要告诉Web API使用添加到Global.asax
的行来查找控制器,只要您引用了控制器,系统就会自动查找控制器。
应该是这样的。清单
- 继承
ApiController
- 以控制器结尾的控制器名称。例:
ValuesController
- 确保WebApi项目和类库项目引用相同的WebApi程序集
- 尝试使用属性路由强制路由
-
Clean
解决方案,手动删除bin
文件夹并重建 - 删除
Temporary ASP.NET Files
文件夹WebApi和MVC缓存控制器查找结果 - 称之为"config.MapHttpAttributeRoutes ();确保框架考虑了属性路由
- 确保你所调用的方法是处理正确的HTTP动词(如果它是一个GET web方法,你可以通过浏览器URL调用,如果它是POST,你必须制作一个web请求)
[RoutePrefix("MyValues")]
public class AbcController : ApiController
{
[HttpGet]
[Route("Get")]
public string Get()
{
return "Ok!";
}
}
匹配这个url:
http://localhost/MyValues/Get
(注意路由中没有/api/
,因为RoutePrefix
中没有指定。
控制器查找缓存:这是默认的控制器解析器。您将在源代码中看到它缓存查找结果。
/// <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 override 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)在配置部分,用新的实现
替换默认值config.Services.Replace(typeof(IAssembliesResolver), new MyNewAssembliesResolver());
我使用这个博客中的指针拼凑了这个语法:
http://www.strathweb.com/2013/08/customizing-controller-discovery-in-asp-net-web-api/正如其他人所说,如果你通过直接引用控制器来强制加载它,你知道你是否遇到了这个问题。另一种方法是举例CurrentDomain.GetAssemblies()
的结果,看看你的程序集是否在列表中。
另外:如果您使用OWIN组件自托管,您将遇到此问题。测试时要记住,DefaultAssembliesResolver在第一个WebAPI请求提交之前不会启动(我花了一段时间才意识到这一点)。
你确定你引用的程序集是在IAssembliesResolver服务被调用之前加载的吗?尝试在应用程序中插入一些虚拟代码,例如
var a = new MyClassLibraryProject.Controllers.MyClass();
中的配置方法(但不要忘记,编译器可以"优化"这段代码并完全删除它,如果"a"从不使用)。我也有类似的装配装载顺序问题。最终在启动时与力加载相关的组件。
你需要告诉webapi/mvc加载你引用的程序集。你可以通过web.config中的编译/汇编部分来完成。
<compilation debug="true" targetFramework="4.5.2">
<assemblies>
<add assembly="XYZ.SomeAssembly" />
</assemblies>
</compilation>
就是这么简单。您可以按照@user1821052建议的方式使用代码来完成,但是这个web。配置版本将具有相同的效果。
除了已经说过的:
确保在不同的命名空间中没有两个同名的控制器。
刚刚有一个控制器(foo.UserApiController)应该部分迁移到一个新的命名空间(bar.UserApiController)和URI的情况。旧的控制器按照约定映射到/userapi,新的控制器通过RoutePrefix["api/users"]
进行属性路由。直到我将它重命名为bar。userfooapicontroller,新控制器才开始工作。
当使用AttributeRouting时,很容易忘记用Route
属性来装饰你的方法,特别是当你在控制器类上使用RoutePrefix
属性时。看起来你的控制器组件没有被web api管道接起。
如果你的类库是用EF
构建的,那么确保你在App.config
中为类库项目指定了连接字符串,在Web.config
中为你的Web API MVC
项目指定了和