How to set timeout of soapclient in .net core project

我的未来我决定 提交于 2019-12-07 05:32:26

Ok If anyone suffers from the same problem, I am posting the solution I found. It seems other people also faced this problem and asked question here

It is a generic error for .Net Core 2.0 as far as i understand and it occurs if request lasts longer than 30 seconds.

As can be seen in upper link, they posted a solution here. It worked for me. Solution requires to make a fake request to service each time before making a real request so timeout settings can be changed. To avoid that I can suggest you to catch "CommunicationException", and apply the solution in that catch. So you make extra calls only if you really need to. I am copying the code, just in case link dies (all credits for code to https://github.com/mconnew/)

   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);}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!