自托管 WebAPI 应用程序引用来自不同程序集的控制器

Posted

技术标签:

【中文标题】自托管 WebAPI 应用程序引用来自不同程序集的控制器【英文标题】:Self-hosting WebAPI application referencing controller from different assembly 【发布时间】:2012-06-14 20:50:28 【问题描述】:

我遇到了this gem,它似乎与我想要的很接近。但是,我想使用引用程序集中已经编写好的控制器。

我的第一次破解是引用程序集,设置路由规则和原来的webAPI项目一样去,但是每次尝试调用自托管服务都会得到400s。我已经通过 Fiddler 挑选了请求的内容,除了地址差异之外,针对 webAPI 项目和自托管项目的请求是相同的。

我觉得这应该是相对简单的,但我还没有找到一个可以接受的答案。

【问题讨论】:

既然 OP 已经明确放弃了这个问题,有没有其他人确认过任何一个提议的解决方案? 没有放弃,我从来没有用有问题的 WebAPI 版本解决问题。 我刚刚验证了@cypressx 提出的建议,它按描述工作。谢谢。 【参考方案1】:

这似乎是一个已知问题。您必须强制 .NET 使用您需要的控制器加载程序集。

在您自行托管 Web API 之前,您应该从参考程序集中检索您希望由运行时加载的类型。像这样的:

Type controllerType = typeof(ReferencedControllers.ControllerType);

这应该从这个程序集中加载控制器,它不会给你 404 错误。

【讨论】:

我已经确认这是正确的信息。我的步骤:(1)创建新的 MVC4 项目,(2)创建新的类库项目,(3)将 MVC4 WebAPI NuGet 包添加到类库项目(4)从 Web 项目引用类库(5)将 Web API 控制器添加到类库项目 (5) 修改Application_Start 与上面建议的代码类似的行。我能够导航到类库项目中定义的 webapi 控制器,所有请求都按预期运行。 似乎适用于当前版本的 WebAPI。谢谢,肖恩! 请注意,那一行:Type controllerType = typeof(ReferencedControllers.ControllerType);仅适用于调试模式,发布时优化忽略它.. 您可以做的另一件事是在自托管它的 .exe 项目中添加对 web api dll 的引用。如果你不引用它,它可能不会被复制到运行时文件夹中。 简单地引用类型依赖于 DefaultAssembliesResolver 来完成工作。 Eric Boumendil 的回答确保程序集被正确加载,并且不会被编译器意外优化掉......【参考方案2】:

link 为同样的问题节省了我的时间 :)...

我只需要更改以下语句以适应 selfhost webapi 配置。

GlobalConfiguration.Configuration.Services.Replace(typeof(IAssembliesResolver), new CustomAssemblyResolver());

var config = new HttpSelfHostConfiguration("http://localhost:8081");
        config.Services.Replace(typeof(IAssembliesResolver), new CustomAssemblyResolver());

【讨论】:

这个链接节省了一天.....我有MS“简单示例”,没有任何分层。谢谢!【参考方案3】:

Praveen 和 Janushirsha 以前的帖子引导我走向正确的方向,我在这里继续:

// Not reliable in Release mode :
Type controllerType = typeof(ReferencedControllers.ControllerType);

因此,您应该将IAssembliesResolver 替换为:

HttpConfiguration config = new HttpConfiguration();
config.Services.Replace(typeof(IAssembliesResolver), new CustomAssembliesResolver());

这是CustomAssembliesResolver的实现示例

using System.Web.Http.Dispatcher;
internal class CustomAssembliesResolver : DefaultAssembliesResolver

    public override ICollection<System.Reflection.Assembly> GetAssemblies()
    
        var assemblies = base.GetAssemblies();

        // Interestingly, if we push the same assembly twice in the collection,
        // an InvalidOperationException suggests that there is different 
        // controllers of the same name (I think it's a bug of WebApi 2.1).
        var customControllersAssembly = typeof(AnotherReferencedAssembly.MyValuesController).Assembly;
        if (!assemblies.Contains(customControllersAssembly))
            assemblies.Add(customControllersAssembly);

        return assemblies;
    

如果未引用第三方程序集或您想要后期程序集绑定,则可以轻松修改此代码。

希望对您有所帮助。

【讨论】:

这帮助很大。谢谢!我认为这应该是公认的答案。 感谢您的评论。很高兴为您提供帮助。 我很难理解你的例子。我正在制作一个启动 webApi 服务的组件。我想从外部应用程序将控制器注入其中。这可能吗?它似乎只是在它自己的项目中神奇地找到了控制器? (我不确定它是如何与这些绑定的……某种幕后反射魔法) 如果我理解您想要达到的目标,答案是肯定的,这是可能的。如果您像示例中那样设置了 IAssembliesResolver,它应该能够解析来自另一个程序集的控制器。 我在这里遇到了类似的问题:***.com/questions/48652339/…,我的 CustomAssembliesResolver 没有被调用。

以上是关于自托管 WebAPI 应用程序引用来自不同程序集的控制器的主要内容,如果未能解决你的问题,请参考以下文章

WebApi控制器使用类库

如何在本地服务结构集群中部署和访问来宾可执行文件(ASP.NET OWIN 自托管 webapi 应用程序)

Azure Functions:引用程序集的配置文件

使用来自另一个 MEF 程序集的类而不引用它

Angular $resource 和自托管 WebAPI 的 CORS 问题

在自托管 Web 应用程序中使用性能计数器