Как настроить WCF для поддержки FaultContracts, когда хост и клиент находятся в одном процессе с использованием net.pipe?
-
03-07-2019 - |
Вопрос
Я пытаюсь создать внутрипроцессный модульный тест для взаимодействия моей службы с клиентом, используя привязку net.pipe.Как и хорошая служба WCF, она использует FaultContractAttribute в операциях службы, чтобы выявить возможные ошибки. (обернутые исключения) к метаданным.Я хотел бы настроить конечные точки клиента и службы через XML. (Приложение.конфигурация). Однако всякий раз, когда выдается ошибка, это просто 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>
Решение
Если описанный выше класс ValidationException — это класс, который вы используете для ошибок, он может быть источником вашей проблемы.Исключения ошибок следует получать из FaultException, поскольку они сериализуемы.ApplicationException нет.
Вагнер прав: вам нужно дополнить определение операции атрибутом FaultContract, указав тип вашего контракта.Вам также следует украсить свой FaultContract атрибутами DataContract и DataMember.
Другие советы
У меня такая же ошибка появилась несколько дней назад.
Я решил создать свой собственный класс (MyFault), выбросить FaultException с сервера и перехватить его на клиенте.MyFault имеет строковый элемент, который представляет собой сообщение об исключении, которое я хочу, чтобы клиент увидел.
Надеюсь, я ясно выразился...Я постараюсь найти хороший образец и выложу его здесь.
Проблема, скорее всего, заключается в ошибке десериализации или сериализации запроса или ответа.Включите трассировку и просмотрите журнал с помощью svctraceviewer, чтобы узнать точную ошибку.
Кроме того, убедитесь, что ваше исключение ошибки помечено [DataContract] и не наследует классы, отличные от [DataContract].
И последнее, что хотелось бы добавить.Определяют ли ваши операционные контракты ServiceFault, который они используют?
Насколько я понимаю, вам нужно определить, какие ServiceFault вы используете на рабочем уровне, и ваша бизнес-логика выдает исключение FaulException, где T — это ServiceFault, который вы определили.