Объект связи, System.ServiceModel.Channels.ServiceChannel, не может использоваться для связи - PullRequest
138 голосов
/ 04 мая 2010

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

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

Ответы [ 14 ]

133 голосов
/ 04 мая 2010

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

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

27 голосов
/ 16 февраля 2013

Чтобы предотвратить падение Сервера в состояние «Сбой», необходимо убедиться, что не возникло необработанного исключения. Если 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 для подробного примера.

8 голосов
/ 21 апреля 2012

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

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

7 голосов
/ 04 мая 2010

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

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

2 голосов
/ 08 апреля 2016

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

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

1004

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

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

2 голосов
/ 21 декабря 2012

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

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

1 голос
/ 23 ноября 2018

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

1 голос
/ 13 мая 2015

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

1 голос
/ 13 февраля 2014

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

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

0 голосов
/ 27 февраля 2019

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...