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?
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