好的,我的情况要复杂得多,但有一种简单的方法可以重现。从一个全新的 ASP.NET MVC 4 Web应用程序项目开始,选择Web API作为模板,我只需在HomeController中添加第二个mvc操作,我需要在内部调用Web API。
public async Task<string> TestAPI()
{
HttpServer server = new HttpServer(GlobalConfiguration.Configuration);
using (HttpMessageInvoker messageInvoker = new HttpMessageInvoker(server, false))
{
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "http://localhost:58233/api/values");
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var response = messageInvoker.SendAsync(request, new CancellationToken()).Result;
return await response.Content.ReadAsStringAsync();
}
//server.Dispose(); - if I do that on the second request I get a "Cannot access a disposed object." exception
}
那件事只适用于第一个请求。在随后的请求中,它会抛出
'DelegatingHandler'列表无效,因为该属性 'RequestMessageHandlerTracer'的'InnerHandler'不为空。参数 名称:处理程序
我真的需要在这里使用GlobalConfiguration.Configuration,因为我的系统是非常模块化/基于插件的,这使得在动作方法(或其他任何地方)内重建该配置非常困难。
答案 0 :(得分:2)
我建议尝试在次要请求上重用HttpServer实例。在每个请求上创建和配置新服务器不是预期的用法,您可能会遇到一些边缘情况。设置DI机制并向控制器注入HttpServer的单例,或者尝试从某个静态属性访问它。
我也建议使用new HttpClient(httpServer)
而不是HttpMessageInvoker。
答案 1 :(得分:0)
如果您有多个HttpServer
使用相同的配置对象,并且配置包含非空的委派处理程序列表,则Web API中可能会出现同样的问题。
发生错误是因为MVC / Web API在第一次请求时构建了一个处理程序管道,其中包含所有委托处理程序(如果启用了请求跟踪,则为RequestMessageHandlerTracer
)相互链接,后跟MVC服务器处理程序。
如果您有多个HttpServer
使用相同的配置对象,并且配置对象包含委托处理程序,则第一个HttpServer
将成功连接到管道中;但第二个不会,因为委托处理程序已经连接 - 相反它会在第一次请求/初始化时抛出此异常。
此处有关Web API案例的更多详细信息(概念上相同,但使用的是不同的类,并且修改稍有不同): webapi batching and delegating handlers
在我看来,MVC配置类应该是纯配置,不包含实际的委托处理程序。相反,配置类应该在初始化时创建新的委托处理程序。那么这个bug就不存在了。