Как установить таймаут мыльного клиента в основном проекте.net
Я должен использовать службу SOAP в проекте.Net Core 2.0. Я добавил сервисную ссылку, как описано в следующей ссылке: https://marketplace.visualstudio.com/items?itemName=WCFCORETEAM.VisualStudioWCFConnectedService
Сервис работает нормально для некоторых методов. Однако некоторые методы занимают много времени (из-за операций, выполняемых службой), и в этом случае программа выдает исключение:"System.Net.Http.WinHttpException: истекло время ожидания операции"
Я попытался установить значение тайм-аута, но это не имеет никакого эффекта.
MyService.MyServiceSoapClient Pr = new MyService.MyServiceSoapClient(new MyService.MyServiceSoapClient.EndpointConfiguration());
Pr.InnerChannel.OperationTimeout = new TimeSpan(0, 10, 0);
Я также проверил следующую ссылку, которая содержит вопросы о службах wcf / soap в.Net Core: https://github.com/dotnet/wcf/issues?page=1&q=is%3Aissue+label%3Atooling&utf8=%E2%9C%93
Но пока нет решения. Есть идеи, как решить эту проблему?
3 ответа
Хорошо, если кто-то страдает от той же проблемы, я публикую решение, которое я нашел. Кажется, другие люди тоже сталкивались с этой проблемой и задавали здесь вопрос
Насколько я понимаю, это общая ошибка.Net Core 2.0, которая возникает, если запрос длится дольше 30 секунд.
Как видно из верхней ссылки, здесь выложено решение. Это сработало для меня. Решение требует, чтобы перед выполнением реального запроса каждый раз выдавался поддельный запрос на обслуживание, чтобы можно было изменить настройки тайм-аута. Чтобы избежать этого, я могу предложить вам перехватить "CommunicationException" и применить решение в этой ловушке. Таким образом, вы делаете дополнительные звонки, только если вам действительно нужно. Я копирую код, на всякий случай ссылка умирает (все кредиты за код на 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);}
В .Net7 я нашел эту опцию
client.ChannelFactory.Endpoint.Binding.SendTimeout = TimeSpan.FromMinutes(10);
Мне не удалось найти метод DelayedResponseAsync в клиентском объекте. Но я мог видеть OpenAsync