Объект связи, System.ServiceModel.Channels.ServiceChannel, не может использоваться для связи

156

Объект связи System.ServiceModel.Channels.ServiceChannel нельзя использовать для связи, поскольку он находится в состоянии Failed.

Что это за ошибка, и как мне ее решить?

Innova
источник

Ответы:

151

Вы получаете эту ошибку, потому что вы допустили исключение .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
    }

    Если это так, все, что вы можете сделать, это избавиться от него и заново создать прокси на стороне клиента, а затем повторите попытку.

marc_s
источник
11
Похоже, такая же ошибка может возникать, когда проблема также на стороне клиента: например, когда квота размера сообщения для входящих сообщений была превышена.
svick
6
Как я могу заново создать клиента?
Масуд
32

Чтобы предотвратить падение Сервера в состояние «Сбой», необходимо убедиться, что не возникло необработанного исключения. Если WCF видит неожиданное исключение, звонки больше не принимаются - безопасность прежде всего.
Две возможности избежать такого поведения:

  1. Используйте 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)   
    }
  2. Скажите WCF обработать все исключения с помощью обработчика ошибок. Это можно сделать несколькими способами, я выбрал простой, используя атрибут:
    все, что нам нужно сделать, это использовать атрибут [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 для подробного примера.

BerndK
источник
10

На самом деле, в случае неудачи после следующих предложений marc_s , имейте в виду, что элемент <security> в конфигурации привязки сервера (или его отсутствие) в файле web.config на сервере может вызвать это исключение. Например, сервер ожидает уровня Messageбезопасности, а клиент настроен на None(или, если сервер не является частью домена Active Directory, а удаленный клиентский узел).

Совет: в таких случаях клиентское приложение, скорее всего, будет нормально вызывать веб-службу при выполнении непосредственно на компьютере сервера под учетной записью администратора в сеансе RDP.

timmi4sa
источник
2

Чтобы диагностировать эту проблему, запустите службу в отладчике Visual Studio. Используйте меню «Отладка | Исключения» и укажите, что вы хотите прервать работу при возникновении исключения.

Исходное сгенерированное исключение будет иметь гораздо лучшее сообщение об ошибке, чем "..я находится в состоянии Faults".

Например, я получал это исключение от ServiceHost.Open (), но когда я поймал исходное исключение во время его появления, сообщение об ошибке было:

Служба «MyServiceName» не имеет конечных точек приложения (не инфраструктуры). Это может быть связано с тем, что для вашего приложения не найден файл конфигурации, или из-за невозможности найти элемент службы, соответствующий имени службы, в файле конфигурации или из-за отсутствия конечных точек в элементе службы.

Исправление орфографической ошибки в App.config решило проблему.

Дейл Уилсон
источник
В VS2015 выберите «Отладка» → «Настройки исключений» и отметьте «Исключения общего времени выполнения».
SharpC
1
Так почему же оригинальное исключение не было выдано, пока вы не использовали отладчик Visual Studio?
Jez
2

У меня была такая же проблема при попытке использовать конечную точку службы 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и очень важно , как на местах источника и клиент должны быть настроены в том же путь.

ppenchev
источник
1

У меня была другая проблема, о которой я не думаю, что она упоминалась в других ответах.

Я должен обслуживать конечные точки по тому же адресу и порту TCP. В app.config я забыл добавить обе конечные точки, поэтому служба работала на правильном порту, но с неправильным интерфейсом службы.

Карстен
источник
1

Если вы видите это сообщение в Debug от Visual Studio и решение содержит проект WCF. Затем откройте настройки проекта WCF -> перейдите на вкладку «Параметры WCF» -> отключите опцию «Запуск хоста WCF при отладке ...»

Хорев Иван
источник
У меня была такая же проблема, и я довольно долго застрял в этой проблеме. Вероятно, не рекомендуется использовать и клиент, и сервер в одном решении. Спасибо!
Юша
1

Для меня проблема была вызвана тем, что файл конфигурации был автоматически создан путем импорта WSDL. Я обновил привязку к из basicHttpBinding для customBinding. Добавление дополнительной обработки исключений не помогло указать на это.

Перед

<basicHttpBinding>
            <binding name="ServiceName">
                <security mode="Transport" />
            </binding>
        </basicHttpBinding>`

После

<customBinding>
        <binding name="ServiceName">
          <textMessageEncoding messageVersion="Soap12" />
          <httpsTransport />
        </binding>
      </customBinding>`
BGotIt
источник
0

В моем случае причина была в неправильном сертификате, который не мог быть загружен. Я узнал об этом из средства просмотра событий в разделе Система:

Произошла неустранимая ошибка при попытке доступа к закрытому ключу учетных данных сервера TLS. Код ошибки, возвращаемый криптографическим модулем, - 0x8009030D. Состояние внутренней ошибки 10001.

altumano
источник
0

Эта ошибка также может быть вызвана вашим собственным компьютером, а не просто необработанным исключением. Если время вашего сервера / компьютера отключено на слишком много минут, многие веб-службы .NET отклонят ваш запрос с необработанной ошибкой. Это обрабатывается с их точки зрения, но не обрабатывается с вашей точки зрения. Убедитесь, что часы вашего принимающего сервера правильные. Если это необходимо исправить, вам придется сбросить службу или перезагрузить компьютер, прежде чем канал откроется снова.

Я столкнулся с этой проблемой на сервере, где брандмауэр заблокировал обновление времени в Интернете, и сервер по какой-то причине отключился. Все сторонние веб-сервисы .NET оказались неисправными, поскольку отклонили любой запрос веб-сервиса. Копание в Event Viewer помогло определить проблему, но настройка часов решила ее. Ошибка была на нашем конце, даже несмотря на то, что мы получили сообщение об ошибке Failed State для будущих вызовов веб-службы.

HBlackorby
источник
0

Сервер автоматически прервет соединения, по которым не было получено ни одного сообщения в течение времени ожидания (по умолчанию 10 минут ). Это предотвращение DoS-атак, чтобы клиенты не заставляли сервер открывать соединения в течение неопределенного периода времени.

Поскольку сервер прерывает соединение из-за простоя, клиент получает это исключение.

Вы можете контролировать, как долго сервер позволяет соединению бездействовать, прежде чем прерывать его, настроив тайм-аут приема для привязки сервера. Кредит: TRVishwanath - MSFT

Виджай Рана
источник
0

Я знаю, что это старый пост, но одна вещь, на которую нужно обратить внимание, когда вы не можете изменить защиту, это убедиться, что установлены ваши имя пользователя и пароль.

У меня был сервис с authenticationMode как UserNameOverTransport, когда имя пользователя и пароль не были установлены для клиента сервиса, я получал эту ошибку.

Джошуа Дж
источник
0

Для меня это была проблема балансировки нагрузки / URL. Веб - сервис за подсистему балансировки нагрузки называется другой служба за ту же балансировку нагрузки , используя полный URL , как: loadbalancer.mycompany.com. Я изменил его, чтобы обойти балансировщик нагрузки при вызове второго сервиса, используя localhost.mycompany.comвместо этого.

Я думаю, что с балансировщиком нагрузки произошла какая-то круговая ссылка.

goku_da_master
источник
-2

Не решение этой проблемы, но если вы столкнулись с вышеуказанной ошибкой в ​​Ektron eSync, возможно, в вашей базе данных недостаточно дискового пространства.

Изменить: На самом деле это не только проблема Ektron eSync. Это может произойти с любым сервисом, который запрашивает полную базу данных.

Изменить: из-за недостатка места на диске или блокировка доступа к каталогу, который вам нужен, может вызвать эту проблему.

Джонатан Бик
источник
Это не дает ответа на вопрос. Чтобы критиковать или запрашивать разъяснения у автора, оставьте комментарий под его постом - вы всегда можете комментировать свои собственные посты, и, когда у вас будет достаточно репутации, вы сможете комментировать любой пост .
Дариуш
2
Я ответил на его вопрос «как бы я решил эту проблему?», Я не виноват, что он никогда не давал нам подробностей о том, использует ли он Ektron или нет. Я также требую 50 повторений, чтобы прокомментировать его пост.
Джонатан Бик