如何使用FaultException进行路由服务自定义筛选器回复?

时间:2014-08-02 15:41:39

标签: c# wcf routing

案例:

首先,我将解释配置文件的当前情况然后我会问我的问题: 我们有两个WCF双工服务(OrdinaryCustomerService,PremiumCustomerService)。这两个服务是相同的,只包含一个操作" DoOperation"并通过名为(ICustomerCallBack)的Callback回复客户端,该回调只包含一个操作(Notify)。 源代码:

[ServiceContract(CallbackContract = typeof (ICustomerCallBack))]
public interface ICustomer
{

    [OperationContract] 
    [FaultContract(typeof (FaultException))]
    void DoOperation();

}

public interface ICustomerCallBack
{

    [OperationContract(IsOneWay = true)]
    void Notify(String message);

}

我们还有路由服务(CustomerService),它将传入的消息转发到OrdinaryCustomerService或PremiumCustomerService,并且此选择基于路由表中的自定义过滤器。路由服务有两个自定义过滤器HiBillingFilter和LowBillingFilter 过滤器检查呼叫者身份是否与存储的身份匹配,然后检查呼叫者等级,有三个选项: 首先:调用者ID与存储的匹配和与存储的排名匹配,然后过滤器必须将消息转发到指定的服务器。 第二:呼叫者ID与存储但匹配并不匹配,然后过滤器必须检查下一个过滤器 第三:调用者ID不匹配,然后Match方法必须正常关闭连接并发送FaulException和Message,用户无法连接,这是我们的问题。 我将向您展示WebConfig用于托管App First然后我将解释该问题

主持应用程序的WebConfig是:

  <system.serviceModel>
    <bindings>
      <netTcpBinding>
        <binding name="NetTcpBinding_ICustomer" maxBufferPoolSize="2147483647" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647" receiveTimeout="00:10:00" sendTimeout="00:10:00">
          <readerQuotas maxDepth="32" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
          <security mode="Transport">
            <transport clientCredentialType="Windows" />
          </security>
        </binding>
      </netTcpBinding>
    </bindings>
    <client>
      <endpoint address="net.tcp://localhost:808/OrdinaryCustomerService/" binding="netTcpBinding" contract="*" name="CustomerServiceLibrary_OrdinaryCustomerService" />
      <endpoint address="net.tcp://localhost:807/PremiumCustomerService" binding="netTcpBinding"  contract="*" name="CustomerServiceLibrary_PremiumCustomerService" />
    </client>
    <services>
      <service name="OrdinaryCustomerService.OrdinaryCustomerService" behaviorConfiguration="normalServiceBehavior" >
        <endpoint address="" binding="netTcpBinding" contract="CustomerContract.ICustomer" bindingConfiguration="NetTcpBinding_ICustomer">
          <identity>
            <dns value="xxx" />
          </identity>
        </endpoint>
        <host>
          <baseAddresses>
            <add baseAddress="net.tcp://localhost:808/OrdinaryCustomerService/" />
          </baseAddresses>
        </host>
      </service>
      <service name="PremiumCustomerService.PremiumCustomerService" behaviorConfiguration="normalServiceBehavior" >
        <endpoint address="" binding="netTcpBinding" contract="CustomerContract.ICustomer" bindingConfiguration="NetTcpBinding_ICustomer">
          <identity>
            <dns value="xxx" />
          </identity>
        </endpoint>
        <host>
          <baseAddresses>
            <add baseAddress="net.tcp://localhost:807/PremiumCustomerService" />
          </baseAddresses>
        </host>
      </service>
      <service behaviorConfiguration="RoutingServiceBehavior" name="System.ServiceModel.Routing.RoutingService">
        <host>
          <baseAddresses>
            <add baseAddress="net.tcp://localhost:809/CustomerService/" />
          </baseAddresses>
        </host>
        <endpoint address="" binding="netTcpBinding" contract="System.ServiceModel.Routing.IDuplexSessionRouter"  name="RoutingServiceEndpoint" bindingConfiguration="NetTcpBinding_ICustomer">
          <identity>
            <dns value="xxx" />
          </identity>
        </endpoint>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="RoutingServiceBehavior">
          <serviceDebug includeExceptionDetailInFaults="true" />
          <routing filterTableName="routingRules" routeOnHeadersOnly="False"  />
        </behavior>
        <behavior name="normalServiceBehavior">
          <serviceDebug includeExceptionDetailInFaults="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <routing>
       <namespaceTable>
         <add prefix="cc" namespace="http://schemas.datacontract.org/2004/07/CustomerContract" />
      </namespaceTable> 
      <filters>
        <filter name="HiBillingFilter" filterType="Custom" customType="CustomerService.HiBillingFilter, CustomerService"/>
        <filter name="LowBillingFilter" filterType="Custom" customType="CustomerService.LowBillingFilter, CustomerService"/>
        <filter name="MatchAll" filterType="MatchAll" />
      </filters>
      <filterTables>
        <filterTable name="routingRules">
          <add filterName="HiBillingFilter" endpointName="CustomerServiceLibrary_PremiumCustomerService" priority="2"/>
          <add filterName="LowBillingFilter" endpointName="CustomerServiceLibrary_OrdinaryCustomerService" priority="1"/>
          <add filterName="MatchAll" endpointName="CustomerServiceLibrary_OrdinaryCustomerService" priority="0" />
        </filterTable>
      </filterTables>
      <backupLists>
        <backupList name="CustomerBackupList">
          <add endpointName="CustomerServiceLibrary_OrdinaryCustomerService" />
        </backupList>
      </backupLists>
    </routing>
  </system.serviceModel>

问题:

如何使用FaultException进行过滤回复,而不是将消息转发给服务? 我试着用:

`OperationContext.Current.RequestContext.Reply(newreply);`

但RequestContext始终为null。

我也尝试使用

`OperationContext.Current.Channel`

`IClientChannel channel = OperationContext.Current.GetCallbackChannel<IClientChannel>()`

但我也无法将回复发送给客户。

请帮我解决这个问题,并提前感谢你。

1 个答案:

答案 0 :(得分:0)

<强>答案:

我终于找到了这个问题的解决方案:

1-我们应该在我们调用的操作中放置一个DataContract而不是void。 2-在操作实现中我们可以返回空对象。 3-当我们调用操作时,我们必须将结果设置为变量我的意思是我们应该使用这个代码:

var mock = proxy.DoOperation();

而不是

proxy.DoOperation();

4-使用MessageInspector在路由之前检查即将发送的消息。

问候。