Как вы настраиваете WCF для поддержки FaultContracts, где и хост, и клиент находятся в одном и том же процессе, используя net.pipe? - PullRequest
4 голосов
/ 21 октября 2008

Я пытаюсь создать внутрипроцессный модульный тест для взаимодействия моего сервиса с клиентом, используя привязку net.pipe. Как хороший сервис WCF, он использует FaultContractAttribute для операций сервиса, чтобы выставлять возможные сбои (заключенные в исключительные ситуации) в метаданные. Я хотел бы настроить конечные точки клиента и службы с помощью XML (App.config). Однако всякий раз, когда выдается ошибка, это просто «канал передачи» CommunicationException, а не напечатанная ошибка ожидая.

System.ServiceModel.CommunicationException: There was an error reading from the pipe: The pipe has been ended. (109, 0x6d). 

Я пытался добавить конечную точку IMetadataExchange для net.pipe, но это не сработало. Я тоже попробовал. То, что на Vista, потребовало от меня netsh ACL для конечной точки http. Это тоже не сработало.

Класс пользовательских исключений:

public class ValidationException : ApplicationException { }

Это последняя попытка конфигурации, но она выкачивает "Не удалось найти имя контракта 'IMetadataExchange' в списке контрактов, реализованных службой"

Буду признателен за любые ссылки на примеры или рекомендации, как это сделать.

<system.serviceModel>

  <client>
    <endpoint name="Client"
              contract="IService"
              address="net.pipe://localhost/ServiceTest/"
              binding="netNamedPipeBinding"
              bindingConfiguration="netPipeBindingConfig" />
  </client>

  <services>
    <service
      name="Service"
      behaviorConfiguration="ServiceFaults">
      <host>
        <baseAddresses>
          <add baseAddress="net.pipe://localhost/ServiceTest/"/>
          <add baseAddress="http://localhost/ServiceTest/"/>
        </baseAddresses>
      </host>
      <endpoint
        address=""
        binding="netNamedPipeBinding"
        bindingConfiguration="netPipeBindingConfig"

        name="ServicePipe"
        contract="IService" />
      <endpoint
        address="MEX"
        binding="mexNamedPipeBinding"
        bindingConfiguration="mexNetPipeBindingConfig"
        name="MexUserServicePipe"
        contract="IMetadataExchange" />
    </service>
  </services>

  <bindings>
    <netNamedPipeBinding>
      <binding name="netPipeBindingConfig"
               closeTimeout="00:30:00"
               sendTimeout="00:30:00" />
    </netNamedPipeBinding>
    <mexNamedPipeBinding>
      <binding name="mexNetPipeBindingConfig"></binding>
    </mexNamedPipeBinding>
  </bindings>

  <behaviors>
    <serviceBehaviors>
      <behavior name="ServiceFaults">
        <serviceDebug includeExceptionDetailInFaults="true"/>
      </behavior>
      <behavior name="MEX">
        <serviceMetadata 
          httpGetEnabled="true"
          httpGetUrl="http://localhost/ServiceTest/MEX"/>
      </behavior>
    </serviceBehaviors>
  </behaviors>

</system.serviceModel>

Ответы [ 4 ]

2 голосов
/ 15 декабря 2008

Если класс ValidationException, который вы описываете выше, является классом, который вы используете для ошибок, он может быть источником вашей проблемы. Вы должны получить свои исключения ошибок из FaultException, потому что он сериализуем. ApplicationException не является.

Вагнер прав, вам нужно украсить свое определение операции атрибутом FaultContract, присваивая ему тип вашего контракта. Вам также следует украсить свой FaultContract с помощью атрибутов DataContract и DataMember.

0 голосов
/ 21 октября 2008

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

Также убедитесь, что исключение вашей ошибки помечено [DataContract] и не наследует классы, отличные от [DataContract].

0 голосов
/ 20 ноября 2008

И последнее, что нужно добавить. Определяют ли ваши операционные контракты ServiceFault, который они используют?.

Насколько я понимаю, вы должны определить, какие ServiceFaults вы используете на уровне операций, и ваша бизнес-логика выдает FaulException, где T - это ServiceFault, который вы определили.

0 голосов
/ 21 октября 2008

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

Надеюсь, я все прояснил ... Я постараюсь найти хороший пример и выложу его здесь

...