How to set timeout of soapclient in .net core project

為{幸葍}努か 提交于 2020-01-03 03:09:35

问题


I have to use a SOAP service in a .Net Core 2.0 project. I added service reference as described in following link: (Missing link, 404)

Service is working fine for some methods. However, some methods are taking long time (due to the operations service is doing) and in this case the program is throwing exception:"System.Net.Http.WinHttpException: The operation timed out"

I tried to set the timeout value but it has no effect.

MyService.MyServiceSoapClient Pr = 
    new MyService.MyServiceSoapClient(
            new MyService.MyServiceSoapClient.EndpointConfiguration());

Pr.InnerChannel.OperationTimeout = new TimeSpan(0, 10, 0);

I also checked the folllowing link which has related questions about wcf/soap services in .Net Core: GitHub: dotnet/wcf

But no solution so far. Any idea how to solve this problem?


回答1:


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);}


来源:https://stackoverflow.com/questions/48079244/how-to-set-timeout-of-soapclient-in-net-core-project

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