Відповіді:
Ви отримуєте цю помилку, тому що ви дозволяєте виключенню .NET статися на вашому сервері, і ви її не вловили та не обробили та не перетворили на помилку SOAP.
Тепер, оскільки серверна частина "бомбардувалась", час WCF "зірвав" канал - наприклад, зв'язок між клієнтом та сервером є непридатним - зрештою, схоже, що ваш сервер просто підірвався, тому ви не можете спілкуватися з це більше.
Отже, що вам потрібно зробити:
завжди ловіть і обробляйте помилки на стороні сервера - не дозволяйте .NET-виняткам подорожувати від сервера до клієнта - завжди обертайте їх у сумісні помилки SOAP. Перегляньте інтерфейс WCF IErrorHandler та застосуйте його на стороні сервера
якщо ви збираєтесь надіслати друге повідомлення на свій канал від клієнта, переконайтеся, що канал не знаходиться у несправному стані:
if(client.InnerChannel.State != System.ServiceModel.CommunicationState.Faulted)
{
// call service - everything's fine
}
else
{
// channel faulted - re-create your client and then try again
}
Якщо це так, все, що ви можете зробити, це утилізувати його та знову створити проксі-сервер клієнта ще раз, а потім спробувати ще раз
Щоб запобігти падінню сервера в стані помилок, ви повинні переконатися, що жодне необроблене виключення не піднімається Якщо WCF бачить несподіваний виняток, більше не приймаються дзвінки - спочатку безпеку.
Дві можливості уникнути такої поведінки:
Використовуйте FaultException (це не є несподіваним для WCF, тому WCF знає, що сервер все ще має дійсний стан)
замість
throw new Exception("Error xy in my function")
використовувати завжди
throw new FaultException("Error xy in my function")
можливо, ви можете спробувати .. зловити весь блок і кинути FaultException у всіх випадках винятку
try
{
... some code here
}
catch (Exception ex)
{
throw new FaultException(ex.Message)
}
Скажіть WCF обробляти всі винятки за допомогою Errorhandler. Це можна зробити декількома способами, я вибрав простий, використовуючи атрибут:
Все, що нам потрібно зробити більше, - це використовувати атрибут [SvcErrorHandlerBehaviour]
для потрібної реалізації служби
using System;
using System.Collections.ObjectModel;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
namespace MainService.Services
{
/// <summary>
/// Provides FaultExceptions for all Methods Calls of a Service that fails with an Exception
/// </summary>
public class SvcErrorHandlerBehaviourAttribute : Attribute, IServiceBehavior
{
public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{ } //implementation not needed
public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints,
BindingParameterCollection bindingParameters)
{ } //implementation not needed
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
foreach (ChannelDispatcherBase chanDispBase in serviceHostBase.ChannelDispatchers)
{
ChannelDispatcher channelDispatcher = chanDispBase as ChannelDispatcher;
if (channelDispatcher == null)
continue;
channelDispatcher.ErrorHandlers.Add(new SvcErrorHandler());
}
}
}
public class SvcErrorHandler: IErrorHandler
{
public bool HandleError(Exception error)
{
//You can log th message if you want.
return true;
}
public void ProvideFault(Exception error, MessageVersion version, ref Message msg)
{
if (error is FaultException)
return;
FaultException faultException = new FaultException(error.Message);
MessageFault messageFault = faultException.CreateMessageFault();
msg = Message.CreateMessage(version, messageFault, faultException.Action);
}
}
}
Це простий приклад, ви можете зануритися глибше в IErrorhandler, не використовуючи голий FaultException
, а FaultException<>
тип, який надає додаткову інформацію, див. IErrorHandler для детального прикладу.
Насправді, якщо не вдалося виконати пропозиції marc_s , майте на увазі, що елемент <security> у конфігурації прив'язки сервера (або його відсутність) у web.config на сервері може спричинити цей виняток. Наприклад, сервер очікує Message
рівня безпеки і клієнт налаштований на None
(або, якщо сервер не є частиною домену Active Directory, а хостом віддаленого клієнта).
Порада. У таких випадках клієнтська програма, швидше за все, вимагатиме штрафу веб-служби, коли виконується безпосередньо на серверній машині під адміністративним обліковим записом у сесії RDP.
Щоб діагностувати цю проблему, запустіть службу під налагоджувачем Visual Studio. Скористайтеся меню: Налагодження | Винятки та вкажіть, що ви хочете зламати, коли викинуто виняток.
Оригінальний виняток, викинутий, матиме набагато краще повідомлення про помилку, ніж ".. воно знаходиться у стані несправності".
Наприклад, я отримував цей виняток з ServiceHost.Open (), але коли я потрапив оригінальний виняток під час його викидання, повідомлення про помилку було:
Служба "MyServiceName" має нульову кінцеву точку застосування (неінфраструктура). Це може бути тому, що для вашої програми не знайдено файлу конфігурації або тому, що в файлі конфігурації не було знайдено жодного сервісного елемента, що відповідає імені служби, або тому, що в елементі служби не було визначено кінцевих точок.
Виправлення орфографічної помилки в App.config вирішило проблему.
У мене була така ж проблема, коли я намагався споживати кінцеву точку служби net.tcp wcf у службі http asmx.
Як я бачив, ніхто не писав конкретної відповіді ЧОМУ виникає ця проблема, а лише як правильно впоратися.
Я боровся з цим кілька днів поспіль і, нарешті, з’ясував, звідки в моєму випадку проблема.
Спочатку я думав, що коли ви робите посилання на службу, конфігураційний файл буде налаштований щодо тегу безпеки так само, як і у джерелі, але це було не так, і я повинен подбати про це вручну. У моєму випадку я мав тільки
<netTcpBinding>
<binding name="NetTcpBinding_IAuthenticationLoggerService"
</binding>
</netTcpBinding>`
Пізніше я побачив, що частина безпеки відсутня, і це має виглядати приблизно так
<netTcpBinding>
<binding name="NetTcpBinding_IAuthenticationLoggerService" transferMode="Buffered">
<security mode="None">
<transport clientCredentialType="None"/>
</security>
</binding>
</netTcpBinding>
Друга проблема в моєму випадку полягала в тому, що я використовував transferMode="Streamed"
у моїй службі WCF-джерела, і у клієнта у мене нічого конкретного щодо цього не було, що було погано, тому що за замовчуванням transferMode
є Buffered
і важливо, щоб і джерело, і клієнт були налаштовані в одній і тій же. шлях.
У мене виникла ще одна проблема, яку, на мою думку, не згадували в інших відповідях.
Я повинен обслуговувати кінцеві точки на одній і тій же адресі tcp та порту. У app.config я забув додати обидві кінцеві точки, тому служба працювала на правильному порті, але з неправильним інтерфейсом служби.
Якщо ви бачите це повідомлення у налагодженні від Visual Studio і рішення містить проект WCF. Потім відкрийте ці налаштування проекту WCF -> перейдіть на вкладку "Параметри WCF" -> вимкнено "Запустити хост служби WCF при налагодженні ..."
Для мене проблема була викликана автоматично налаштованим файлом конфігурації імпортом WSDL. Я оновив прив'язку до basicHttpBinding до customBinding. Додавання додаткової обробки винятків не допомогло вказати на це.
До цього
<basicHttpBinding>
<binding name="ServiceName">
<security mode="Transport" />
</binding>
</basicHttpBinding>`
Після
<customBinding>
<binding name="ServiceName">
<textMessageEncoding messageVersion="Soap12" />
<httpsTransport />
</binding>
</customBinding>`
У моєму випадку причиною був неправильний сертифікат, який неможливо було завантажити. Я дізнався про це у засобі перегляду подій у системі:
Фактична помилка сталася під час спроби отримати доступ до приватного ключа облікового запису сервера TLS. Код помилки, повернутий з криптографічного модуля, становить 0x8009030D. Стан внутрішньої помилки 10001.
Цю помилку може спричинити і ваш власний комп'ютер, а не лише необроблений виняток. Якщо у вашого сервера / комп’ютера час роботи вичерпано на занадто багато хвилин, багато веб-сервісів .NET відхилять ваш запит із необробленою помилкою. Це обробляється з їхньої точки зору, але без обробки з вашого погляду. Переконайтесь, що час роботи вашого сервера приймає правильний. Якщо це потрібно виправити, вам доведеться скинути послугу або перезавантажитись, перш ніж канал знову відкриється.
У мене виникла ця проблема на сервері, де брандмауер блокував оновлення часу в Інтернеті, а сервер чомусь вийшов з роботи. Усі сторонні веб-сервіси .NET винили помилково, оскільки вони відхилили будь-який запит веб-служби. Копання у переглядачі подій допомогло визначити проблему, але налаштування годинника вирішило її. Помилка закінчилася, навіть якщо ми отримали повідомлення про помилку держави про помилку для майбутніх викликів веб-служб.
Сервер автоматично припиняє з'єднання, протягом яких не було отримано жодного повідомлення протягом тривалості, що дорівнює часу очікування прийому ( за замовчуванням - 10 хвилин ). Це зменшення DoS, щоб клієнти не змушували сервер відкривати з'єднання на невизначений час.
Оскільки сервер припиняє з'єднання, оскільки він не працює, клієнт отримує цей виняток.
Ви можете керувати тим, як довго сервер дозволяє з'єднанню вийти з режиму очікування, перш ніж перервати його, налаштувавши тайм-аут прийому на прив'язці сервера. Кредит: TRVishwanath - MSFT
Я знаю, що це старіша публікація, але одне, на що слід стежити, коли ви не можете змінити безпеку, - це переконатися, що ваше ім’я користувача та пароль встановлені.
У мене був сервіс з аутентифікацією Mode як UserNameOverTransport, коли ім'я користувача та пароль не були встановлені для клієнта служби, я отримав цю помилку.
Для мене це була проблема балансування навантаження / URL. Веб - сервіс за підсистему балансування навантаження називається інший служба за ту ж балансування навантаження , використовуючи повний URL , як: loadbalancer.mycompany.com
. Я змінив його, щоб обійти балансир навантаження при виклику другої служби, використовуючи localhost.mycompany.com
замість цього.
Я думаю, що з балансиром навантаження виникала якась кругова довідкова проблема.
Це не вирішення цієї проблеми, але якщо ви відчуваєте вищезгадану помилку з Ektron eSync, можливо, у вашій базі даних не вистачає місця на диску.
Редагувати: насправді це не зовсім проблема Ektron eSync. Це може статися на будь-якій службі, яка запитує повну базу даних.
Редагування: відсутність місця на диску або блокування доступу до потрібного каталогу спричинить цю проблему.