【问题标题】:I got an error "System.Net.Http.WinHttpException: The operation timed" after i migrated to .NET Core 2.2迁移到 .NET Core 2.2 后出现错误“System.Net.Http.WinHttpException: The operation timed”
【发布时间】:2019-06-30 05:25:42
【问题描述】:

我正在将我的 API 迁移到 .NET Core 2.2,并且在我的应用程序中调用另一个 wsdl (WCF) 服务。在调用该服务时,我收到一条错误消息

System.Net.Http.WinHttpException:操作计时

我迁移的方式有问题吗?它在我以前在 .net 4.5 上运行的解决方案中完美运行

这是完整的内部短信。

InnerException: System.Net.Http.HttpRequestException: 发送请求时出错。

System.Net.Http.WinHttpException:操作超时

在 System.Threading.Tasks.RendezvousAwaitable``1.GetResult()
在 System.Net.Http.WinHttpHandler.StartRequest(WinHttpRequestState 状态)
--- 内部异常堆栈跟踪结束 --->

在 System.ServiceModel.Channels.ServiceModelHttpMessageHandler.SendAsync(HttpRequestMessage request, CancellationToken cancelToken)
在 System.Net.Http.HttpClient.FinishSendAsyncUnbuffered(Task1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean disposeCts)
at System.ServiceModel.Channels.HttpChannelFactory
1.HttpClientRequestChannel.HttpClientChannelAsyncRequest.SendRequestAsync(消息消息,TimeoutHelper timeoutHelper)

【问题讨论】:

标签: c# api wcf .net-core


【解决方案1】:

您的肥皂请求是否需要超过 30 秒?如果是,您需要知道.NET Core 中soap 请求的默认超时时间是30 秒。

改成超时有点麻烦,不过有人already figured it how

        static void Main(string[] args)
        {
            var client = new SimpleServiceClient();
            client.OpenAsync().GetAwaiter().GetResult();
            client.DelayedResponseAsync(2000).GetAwaiter().GetResult();
            var channel = client.InnerChannel;
            var httpChannelFactory = client.InnerChannel.GetProperty<IChannelFactory>();
            var cacheField = httpChannelFactory.GetType().GetField("_httpClientCache", BindingFlags.NonPublic | BindingFlags.Instance);
            var httpClientCache = cacheField.GetValue(httpChannelFactory);
            var cacheDictionaryField = httpClientCache.GetType().GetField("_items", BindingFlags.NonPublic | BindingFlags.Instance);

            IDictionary cacheDictionary = (IDictionary)cacheDictionaryField.GetValue(httpClientCache);
            foreach(var cacheKey in cacheDictionary.Keys)
            {
                var cacheEntry = cacheDictionary[cacheKey];
                var valueField = cacheEntry.GetType().GetField("value", BindingFlags.NonPublic | BindingFlags.Instance);
                HttpClient httpClient = (HttpClient)valueField.GetValue(cacheEntry);
                FixHttpClient(httpClient);
            }

            client.DelayedResponseAsync(50000).GetAwaiter().GetResult();
            Console.WriteLine("Done");
            Console.ReadLine();
        }

        private static void FixHttpClient(HttpClient httpClient)
        {
            var handlerField = typeof(HttpMessageInvoker).GetField("_handler", BindingFlags.NonPublic | BindingFlags.Instance);
            DelegatingHandler delegatingHandler = (DelegatingHandler)handlerField.GetValue(httpClient); // Should be of type ServiceModelHttpMessageHandler
            WinHttpHandler winHttpHandler = (WinHttpHandler)delegatingHandler.InnerHandler;
            WinHttpHandler newHandler = new WinHttpHandler();
            newHandler.ServerCredentials = winHttpHandler.ServerCredentials;
            newHandler.CookieUsePolicy = winHttpHandler.CookieUsePolicy;
            newHandler.ClientCertificates.AddRange(winHttpHandler.ClientCertificates);
            newHandler.ServerCertificateValidationCallback = winHttpHandler.ServerCertificateValidationCallback;
            newHandler.Proxy = winHttpHandler.Proxy;
            newHandler.AutomaticDecompression = winHttpHandler.AutomaticDecompression;
            newHandler.PreAuthenticate = winHttpHandler.PreAuthenticate;
            newHandler.CookieContainer = winHttpHandler.CookieContainer;

            // Fix the timeouts
            newHandler.ReceiveHeadersTimeout = Timeout.InfiniteTimeSpan;
            newHandler.ReceiveDataTimeout = Timeout.InfiniteTimeSpan;
            newHandler.SendTimeout = Timeout.InfiniteTimeSpan;

            var servicemodelHttpHandlerInnerHandlerField = delegatingHandler.GetType().GetField("_innerHandler", BindingFlags.NonPublic | BindingFlags.Instance);
            servicemodelHttpHandlerInnerHandlerField.SetValue(delegatingHandler, newHandler);
            var delegatingHandlerInnerHandlerField = typeof(DelegatingHandler).GetField("_innerHandler", BindingFlags.NonPublic | BindingFlags.Instance);
            delegatingHandlerInnerHandlerField.SetValue(delegatingHandler, newHandler);
        }

所以很容易,将您的HttpClient 传递给

直接从gist复制代码。

【讨论】:

  • 是的!我编辑了响应超时错误,它完成了工作。我还有另一个问题
猜你喜欢
  • 1970-01-01
  • 2020-08-22
  • 2016-03-17
  • 1970-01-01
  • 2020-03-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-14
相关资源
最近更新 更多