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

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

О чем эта ошибка, и как мне ее решить?

20 ответов

Решение

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

  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 для подробного примера.

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

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

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

Изменить: Было бы также полезно, если бы вы опубликовали дополнительную информацию о том, что вы делаете.

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

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

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

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

Перед

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

После

<customBinding>
        <binding name="ServiceName">
          <textMessageEncoding messageVersion="Soap12" />
          <httpsTransport />
        </binding>
      </customBinding>`

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

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

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

У меня есть веб-клиент, который подключается к службе Windows через WCF. мое веб-приложение выдает ту же ошибку

Объект связи, System.ServiceModel.Channels.ServiceChannel, нельзя использовать для связи, поскольку он находится в состоянии Failed. Я включил трассировку WCF, что не сильно помогло. наконец, перезапуск службы Windows решил ее, и я до сих пор понятия не имею о причине. поэтому устранение неполадок, как всегда, должно начинаться с простого. это наглядный пример. если у кого-то есть подобная проблема, попробуйте перезапустить службу.

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

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

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

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

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

Я перепробовал все ответы, но все равно получил ошибку. Однако у меня ошибка произошла после развертывания на удаленном сервере, а не во время разработки в VS Code.

Итак, мне пришлось обратиться к диспетчеру IIS удаленного сервера. Нажмите «Пул приложений» в меню слева, выберите «Мой сайт», а затем в «Дополнительных настройках» (справа) я установил для параметра «Режим запуска» значение «Всегда работает» вместо «По требованию». Нажал «ОК», и все заработало.

мы используем MSMQ в нашей системе, пришло это сообщение об ошибке. Причина заключалась в том, что наша очередь была заполнена, и мы неправильно обрабатывали механизм регистрации ошибок, поэтому вместо msmq ful мы получали указанное выше исключение. Мы очистили сообщения, после чего все работает нормально.

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

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

Я получил это в VS 2022 v17.5.5, пытаясь отладить классический облачный сервис. Я решил эту проблему, щелкнув правой кнопкой мыши роль, перейдя в «Интернет» и перейдя с использования экспресс-эмулятора на полный эмулятор.

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

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

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

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

Для нас проблема заключалась в том, что веб-сайт не был внесен в белый список, что требовалось нашему приложению. После внесения сайта в белый список ошибка исчезла.

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

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

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

Другие вопросы по тегам