如何配置Web Api 2以在单独的项目中查找控制器?(就像我以前在Web Api中所做的那样)

M. *_*har 49 c# asp.net-web-api asp.net-web-api2

我曾经将我的控制器放在Mvc Web Api中的一个单独的类库项目中.我曾经在我的web api项目的global.asax中添加以下行来查找单独项目中的控制器:

ControllerBuilder.Current.DefaultNamespaces.Add("MyClassLibraryProject.Controllers");
Run Code Online (Sandbox Code Playgroud)

除了添加上面的行之外,我从来没有做过任何其他配置.这对我来说一直很好.

但是我无法使用上述方法在WebApi2中执行相同的操作.它只是不起作用.WebApi2项目仍尝试在其自己项目的controllers文件夹中查找控制器.

- 2个月后给予一点摘要更新(因为我开始对此表示赏心悦目):

我创建了一个WebApiOne解决方案,它有2个项目,第一个是WebApi项目,第二个是控制器的类库.如果我将对控制器类库项目的引用添加到WebApi项目中,则所有内容都按预期工作.即如果我去http://mydevdomain.com/api/values我可以看到正确的输出.

我现在创建了一个名为WebApiTwo的第二个项目,它有2个项目,第一个是WebApi2项目,第二个是控制器的类库.如果我将对控制器类库项目的引用添加到WebApi2项目,它将无法按预期工作.即如果我去http://mydevdomain.com/api/values我得到"没有找到匹配名为'值'的控制器的类型."

对于第一个项目,我根本没有做任何自定义设置,我没有:

ControllerBuilder.Current.DefaultNamespaces.Add("MyClassLibraryProject.Controllers");
Run Code Online (Sandbox Code Playgroud)

在我的global.asax中,我没有在他的两篇博文中实现StrathWeb提出的任何自定义解决方案,因为我认为它不再适用; 因为所有工作只是通过将控制器项目的引用添加到WebApi项目.

所以我希望所有人都能为WebApi2工作......但事实并非如此.有没有人真的尝试在WebAPi2中这样做?

Dav*_*idG 29

我刚刚确认这很好用.要检查的事项:

参考:您的主Web API项目是否引用外部类库?

路由:您是否设置了可能干扰外部控制器的路由?

保护级别:外部库中的控制器是public什么?

继承:外部库中的控制器是否继承ApiController

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

如果有帮助,我可以打包我的测试解决方案并将其提供给您.此外,作为一个注意事项,您不需要告诉Web API查找带有您添加的行的控制器Global.asax,系统会自动查找控制器,前提是您已引用它们.


Nik*_*vić 16

它应该按原样运作.清单

  • 继承 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!";
    }
}
Run Code Online (Sandbox Code Playgroud)

匹配此网址:

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;
    }
...
}
Run Code Online (Sandbox Code Playgroud)

  • 为什么类名必须以Controller结尾?为什么不能继承ApiController? (4认同)

use*_*052 9

遇到了同样的情况,@ 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;

    }
}
Run Code Online (Sandbox Code Playgroud)

2)在配置部分中,将默认值替换为新实现

config.Services.Replace(typeof(IAssembliesResolver), new MyNewAssembliesResolver());
Run Code Online (Sandbox Code Playgroud)

我使用此博客中的指针拼凑了这个语法:

http://www.strathweb.com/2013/08/customizing-controller-discovery-in-asp-net-web-api/

正如其他人所说,如果您通过直接引用控制器来加载控制器,您就会知道是否遇到了这个问题.另一种方法是示例结果CurrentDomain.GetAssemblies()并查看您的程序集是否在列表中.

另外:如果您使用OWIN组件进行自托管,您将遇到此问题.测试时请记住,在提交第一个WebAPI请求之前,DefaultAssembliesResolver不会启动(我花了一些时间才意识到这一点).

  • 不幸的是,您引用的原始代码包含拼写错误,而您的版本也不正确.除非你更正签名(`virtual` - >`override`),否则它将_not_按预期运行.如果你这样做,代码将工作,但如前所述,不使用`assemblies`.删除该赋值,或更正用法,即将对"baseAssemblies.Add"的调用更改为`assemblies.Add`,然后返回`assemblies`,而不是`baseAssemblies`. (3认同)

jus*_*ara 7

在调用IAssembliesResolver服务之前,您确定已加载引用的程序集吗?尝试在您的应用程序中插入一些虚拟代码,例如

var a = new MyClassLibraryProject.Controllers.MyClass();

在配置方法(但不要忘记,如果从未使用"a",该编译器可以"优化"此代码并完全删除它.我有与装配加载订单类似的问题.在启动时使用强制加载相关组件结束.


Rya*_*ann 5

您需要告诉webapi/mvc加载您的referrenced程序集.您可以使用web.config中的compilation/assemblies部分执行此操作.

<compilation debug="true" targetFramework="4.5.2">
  <assemblies>
    <add assembly="XYZ.SomeAssembly" />
  </assemblies>
</compilation>
Run Code Online (Sandbox Code Playgroud)

就那么简单.您可以使用@ user1821052建议的方式使用代码来执行此操作,但此web.config版本将具有相同的效果.