【发布时间】:2020-11-19 16:37:44
【问题描述】:
我目前正在使用用于 C# 的 Azure Devops 客户端库。 由于许多原因(例如避免端口耗尽或可测试性),我想使用 dotnetcore 提供的 IHttpMessageHandlerFactory 来为我的 VssConnection 提供处理程序。 目前,我使用这个:
var vssHttpMessageHandler = new VssHttpMessageHandler(new VssBasicCredential(string.Empty, options.Pat), VssClientHttpRequestSettings.Default.Clone(), _httpMessageHandlerFactory.CreateHandler(HttpClientName));
但是,这并不总是有效,因为当处理程序被重用时,会引发异常:
System.InvalidOperationException 在 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw 处理: 在 System.Net.Http.SocketsHttpHandler.CheckDisposedOrStarted(System.Net.Http,版本=4.2.2.0,文化=中性,PublicKeyToken=b03f5f7f11d50a3a) 在 Microsoft.VisualStudio.Services.Common.VssHttpMessageHandler.ApplySettings(Microsoft.VisualStudio.Services.Common,版本=16.0.0.0,Culture=neutral,PublicKeyToken=b03f5f7f11d50a3a)
事实上,在构造VssHttpMessageHandler时,新的设置被应用到了HttpMessageHandler,然而,这个不支持在它开始使用后被修改(它的所有属性在设置时调用CheckDisposedOrStarted)。
我可以做些什么来实现我想做的事情?
编辑:这是我的代码的复制品
var azureDevopsUri = "https://dev.azure.com/mycollection";
var pat = "mypathere";
var services = new ServiceCollection();
services.AddHttpClient();
services.AddTransient(s =>
{
var handlerFactory = s.GetRequiredService<IHttpMessageHandlerFactory>();
var vssHandler = new VssHttpMessageHandler(
new VssBasicCredential(string.Empty, pat),
VssClientHttpRequestSettings.Default.Clone(),
handlerFactory.CreateHandler());
return new VssConnection(
new Uri(azureDevopsUri),
vssHandler,
new DelegatingHandler[] { });
});
var provider = services.BuildServiceProvider();
using(var scope = provider.CreateScope())
{
var connection = scope.ServiceProvider.GetRequiredService<VssConnection>();
var client = await connection.GetClientAsync<ProjectCollectionHttpClient>();
await client.GetProjectCollections();
}
using (var scope = provider.CreateScope())
{
var connection = scope.ServiceProvider.GetRequiredService<VssConnection>(); // <-- Exception thrown here
var client = await connection.GetClientAsync<ProjectCollectionHttpClient>();
await client.GetProjectCollections();
}
如您所见,当我将 VssConnection 配置为不作为单例时(这是我发现现在正在工作的解决方法),第二次创建实例时,我将异常抛出为用于池的 IHttpMessageHandlerFactory可能已经被使用了。
异常详情:
This instance has already started one or more requests. Properties can only be modified before sending the first request.
at System.Net.Http.SocketsHttpHandler.CheckDisposedOrStarted()
at System.Net.Http.HttpClientHandler.set_AllowAutoRedirect(Boolean value)
at Microsoft.VisualStudio.Services.Common.VssHttpMessageHandler.ApplySettings(HttpMessageHandler handler, ICredentials defaultCredentials, VssHttpRequestSettings settings)
at UserQuery.<>c__DisplayClass4_0.<Main>b__0(IServiceProvider s), line 9
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitFactory(FactoryCallSite factoryCallSite, RuntimeResolverContext context)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitDisposeCache(ServiceCallSite transientCallSite, RuntimeResolverContext context)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Resolve(ServiceCallSite callSite, ServiceProviderEngineScope scope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.DynamicServiceProviderEngine.<>c__DisplayClass1_0.<RealizeService>b__0(ServiceProviderEngineScope scope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
at UserQuery.Main(), line 31
【问题讨论】:
-
您可以参考答案中的示例。由于我无法根据您的代码重现此问题,您能否分享更多示例代码和重现此问题的步骤?另一方面,您可以直接将参数分配给 vssconnection 以进行连接。docs.microsoft.com/en-us/azure/devops/integrate/get-started/…
-
我已经用复制更新了我的消息。问题是重用池提供的 HttpMessageHandler 时。
-
嗨@Nathanael Marchand。感谢你的信息。我可以重现这个问题。根据我的测试,如果我删除
handlerFactory.CreateHandler(),它将成功构建。能否请您尝试一下,看看它是否可以做出一些改变。 -
是的,我知道我可以让 sdk 创建处理程序,但它可能会导致套接字耗尽。这就是为什么我想使用 aspnetcore/dotnetcore 带来的池化改进(参见docs.microsoft.com/en-us/aspnet/core/fundamentals/…)
标签: c# .net-core azure-devops