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

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

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

Ответ 1

Вы получаете эту ошибку, потому что вы допускаете исключение .NET на своей стороне сервера, и вы не поймали и не обработали ее, а также не преобразовали ее в ошибку SOAP.

Теперь, когда серверная сторона "бомбирована", среда выполнения WCF "оборвала" канал - например, связь между клиентом и сервером непригодна для использования - в конце концов, похоже, что ваш сервер просто взорвался, поэтому вы больше не можете общаться с ним.

Итак, что вам нужно сделать:

  • всегда улавливать и обрабатывать ошибки на стороне сервера - не выполнять разрешать исключения .NET от сервера к клиенту - всегда strong > оберните их в совместимые ошибки SOAP. Проверьте интерфейс WCF IErrorHandler и реализуйте его на стороне сервера

  • если вы собираетесь отправить второе сообщение на свой канал от клиента, убедитесь, что канал не находится в неисправном состоянии:

    if(client.InnerChannel.State != System.ServiceModel.CommunicationState.Faulted)
    {
       // call service - everything fine
    }
    else
    {
       // channel faulted - re-create your client and then try again
    }
    

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

Ответ 2

Чтобы сервер не попал в состояние Fault, вы должны убедиться, что необработанное исключение не создано. Если 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 обойти все Исключения, используя Обработчик ошибок. Это можно сделать несколькими способами, я выбрал простой, используя атрибут:
    Все, что нам нужно сделать больше, - использовать атрибут [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.

Ответ 3

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

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

Ответ 4

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

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

Ответ 5

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

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

Ответ 6

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

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

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

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

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

Ответ 7

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

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

Ответ 8

Если вы видите это сообщение в Debug из Visual Studio, а решение содержит проект WCF. Затем откройте настройки этого проекта WCF → перейдите на вкладку "Параметры WCF" → выкл. "Запустить узел WCF Service Host при отладке..."

Ответ 9

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

Ответ 10

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

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

Ответ 11

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

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

Ответ 12

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

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

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

Ответ 13

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

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

Ответ 14

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

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

Ответ 15

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

Перед

<basicHttpBinding>
            <binding name="ServiceName">
                <security mode="Transport" />
            </binding>
        </basicHttpBinding>'
После того, как

After

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

Ответ 16

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

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

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