.net core项目中soapclient的超时设置方法
How to set timeout of soapclient in .net core project
我必须在 .Net Core 2.0 项目中使用 SOAP 服务。我按照以下 link 中的描述添加了服务参考:(Missing link, 404)
某些方法的服务工作正常。但是,有些方法需要很长时间(由于操作服务正在执行),在这种情况下程序会抛出异常:"System.Net.Http.WinHttpException: The operation timed out"
我尝试设置超时值但没有效果。
MyService.MyServiceSoapClient Pr =
new MyService.MyServiceSoapClient(
new MyService.MyServiceSoapClient.EndpointConfiguration());
Pr.InnerChannel.OperationTimeout = new TimeSpan(0, 10, 0);
我还检查了以下 link,其中有关于 .Net Core 中 wcf/soap 服务的相关问题:GitHub: dotnet/wcf
但目前还没有解决办法。知道如何解决这个问题吗?
好的,如果有人遇到同样的问题,我会发布我找到的解决方案。看来其他人也遇到过这个问题并提出问题here
据我所知,这是 .Net Core 2.0 的一般错误,如果请求持续时间超过 30 秒,就会发生。
上面可以看到link,他们贴出了解决方案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);}
我必须在 .Net Core 2.0 项目中使用 SOAP 服务。我按照以下 link 中的描述添加了服务参考:(Missing link, 404)
某些方法的服务工作正常。但是,有些方法需要很长时间(由于操作服务正在执行),在这种情况下程序会抛出异常:"System.Net.Http.WinHttpException: The operation timed out"
我尝试设置超时值但没有效果。
MyService.MyServiceSoapClient Pr =
new MyService.MyServiceSoapClient(
new MyService.MyServiceSoapClient.EndpointConfiguration());
Pr.InnerChannel.OperationTimeout = new TimeSpan(0, 10, 0);
我还检查了以下 link,其中有关于 .Net Core 中 wcf/soap 服务的相关问题:GitHub: dotnet/wcf
但目前还没有解决办法。知道如何解决这个问题吗?
好的,如果有人遇到同样的问题,我会发布我找到的解决方案。看来其他人也遇到过这个问题并提出问题here
据我所知,这是 .Net Core 2.0 的一般错误,如果请求持续时间超过 30 秒,就会发生。
上面可以看到link,他们贴出了解决方案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);}