如何配置 WCF 以支持故障契约,其中主机和客户端都在使用 net.pipe 的同一进程中?

发布于 2024-07-07 18:58:21 字数 2660 浏览 5 评论 0原文

我正在尝试使用 net.pipe 绑定为我的服务与客户端交互创建一个进程内单元测试。 与良好的 WCF 服务一样,它在服务操作上使用FaultContractAttribute 将可能的错误(包装的异常)暴露给元数据。 我希望通过 XML 配置客户端和服务端点(App.config)。但是,每当抛出故障时,它只是一个 CommunicationException“管道已关闭”,而不是键入的故障 I正在期待。

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

我尝试为 net.pipe 添加 IMetadataExchange 端点,但这不起作用。 我也尝试过。 在 Vista 上,需要我对 http 端点的 ACL 进行 netsh 操作。 那也行不通。

自定义异常类:

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>

I'm trying to create an in-process unit test for my service to client interactions using net.pipe binding. Like a good WCF service it uses FaultContractAttribute on service operations to expose possible faults (wrapped exceptions) to metadata. I would like to have the client and service endpoints configured thru XML (App.config). However, whenever a fault is thrown, it's just a CommunicationException "pipe has closed", and not the typed Fault I was expecting.

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

I tried Adding IMetadataExchange endpoint for net.pipe, but that didn't work. I also tried . Which being on Vista required me to netsh the ACL for the http endpoint. That too did not work.

The custom exception class:

public class ValidationException : ApplicationException { }

This is the latest attempt at a config, but it pumps out "The contract name 'IMetadataExchange' could not be found in the list of contracts implemented by the service"

Any Links to examples or recommendations for how to get this done would be appreciated.

<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>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

韬韬不绝 2024-07-14 18:58:21

如果您上面描述的 ValidationException 类是您用于处理错误的类,那么它可能是问题的根源。 您应该从FaultException 派生错误异常,因为它是可序列化的。 ApplicationException 不是。

Wagner 是对的,您需要用一个FaultContract 属性来装饰您的操作定义,并赋予它您的合约类型。 您还应该使用 DataContract 和 DataMember 属性来装饰您的FaultContract。

If the ValidationException class you describe above is the class you are using for faults, it may be the source of your problem. You should derive your fault exceptions from FaultException because it is Serializable. ApplicationException is not.

Wagner is right, you need to decorate your operation definition with a FaultContract attribute giving it the type of your contract. You should also to decorate your FaultContract with DataContract and DataMember attributes as well.

甜嗑 2024-07-14 18:58:21

几天前我也遇到了同样的错误。
我解决了创建自己的类(MyFault)并从服务器抛出FaultException并在客户端捕获这些异常的问题。 MyFault 有一个字符串成员,它是我希望客户端看到的异常消息。

我希望我说清楚了......我会尝试寻找一个好的样本,然后将其发布在这里

I got that same error a few days ago.
I solved creating my own class (MyFault) and throwing FaultException from the server and catching those in the client. MyFault has a string member wich is the Exception Message I want the client to see.

I hope I made myself clear... I'll try to look for a nice sample and I'll post it here

天煞孤星 2024-07-14 18:58:21

该问题很可能是反序列化或序列化请求或响应时出现错误。 启用跟踪并使用 svctraceviewer 查看日志以获取确切的错误。

另外,请确保您的错误异常标记为 [DataContract] 并且不继承非 [DataContract] 类。

The problem is most likely an error deserializing or serializing the request or response. Enable trace and view the log with svctraceviewer for the exact error.

Also, make sure your fault exception is marked with [DataContract] and does not inherit and non [DataContract] classes.

誰認得朕 2024-07-14 18:58:21

最后要补充的一件事。 您的操作合同是否定义了他们正在使用的 ServiceFault?

我的理解是,您必须定义在操作层使用哪些 ServiceFault,并且您的业务逻辑会抛出 FaulException,其中 T 是您定义的 ServiceFault。

One last thing to add. Do your operation contracts define the ServiceFault they are using?.

My understanding is that you have to define which ServiceFaults your're using at the operation layer, and your business logic throw a FaulException where T is the ServiceFault you defined.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文