有时在项目中,由于部署的原因。我们需要对原来的WCF Service做一个代理,实现消息完全转发。WCF中我们可以这样实现,假设有这样的Service

   1:      [ServiceContract]
   2:      public interface IMath
   3:      {
   4:          [OperationContract]
   5:          double Add(double A, double B);
   6:      }

实现:
   1:      public class Math : IMath
   2:      {
   3:          public double Add(double A, double B)
   4:          {
   5:              return A + B;
   6:          }
   7:      }

然后我们Host一个service, address是 http://localhost:24258/Math.svc ,然后我们测试它:

   1:          [TestMethod]
   2:          public void TestMessageForSVCHost()
   3:          {
   4:              using (var myChannelFactory = new ChannelFactory<IMath>(new BasicHttpBinding(), "http://localhost:24258/Math.svc"))
   5:              {
   6:                  // Create a channel.
   7:                  IMath wcfClient1 = myChannelFactory.CreateChannel();
   8:                  var s = wcfClient1.Add(1, 234);
   9:                  Console.WriteLine(s.ToString());
  10:                  ((IClientChannel)wcfClient1).Close();
  11:   
  12:                  myChannelFactory.Close();
  13:   
  14:                  Assert.AreEqual(235, s);
  15:              }
  16:          }

现在我们来增加一个Proxy Interface:

    using System.ServiceModel;
    using System.ServiceModel.Channels;
 
    /// <summary>
    /// The i pass through service.
    /// </summary>
    [ServiceContract]
    public interface IPassThroughService
    {
        #region Public Methods
 
        /// <summary>
        /// The process message.
        /// </summary>
        /// <param name="message">
        /// The message.
        /// </param>
        /// <returns>a meeage
        /// </returns>
        [OperationContract(Action = "*", ReplyAction = "*")]
        Message ProcessMessage(Message message);
 
        #endregion
    }

实现:

    using System;
    using System.ServiceModel;
    using System.ServiceModel.Channels;
 
    /// <summary>
    /// PassThroughService class
    /// </summary>
    public class PassThroughService : IPassThroughService
    {
        /// <summary>
        /// Processes the message.
        /// </summary>
        /// <param name="requestMessage">The request message.</param>
        /// <returns>response Message</returns>
        public Message ProcessMessage(Message requestMessage)
        {
            using (var factory = new ChannelFactory<IPassThroughService>("testserver"))
            {
                IPassThroughService proxy = factory.CreateChannel();
 
                using (proxy as IDisposable)
                {
                    var responseMessag = proxy.ProcessMessage(requestMessage);
                    return responseMessag;
                }
            }
        }
    }

然后在代理WCF项目,配制节是这样的:

   1:    <system.serviceModel>
   2:      <behaviors>
   3:        <serviceBehaviors>
   4:          <behavior>
   5:            <!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
   6:            <serviceMetadata httpGetEnabled="true"/>
   7:            <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
   8:            <serviceDebug includeExceptionDetailInFaults="true"/>
   9:          </behavior>
  10:        </serviceBehaviors>
  11:      </behaviors>
  12:      <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
  13:      <client>
  14:        <!-- Note: contract use another service contact -->
  15:        <endpoint name="testserver" address="http://localhost:24258/Math.svc" binding="basicHttpBinding"
  16:                   contract="ProxyWCFService.IPassThroughService"/>
  17:      </client>
  18:    </system.serviceModel>

注意第15行代码,我们指定了是我们目标Service address,而Contact则是 IPassThroughService, ProxyWCFService是Namespace.

然后我们Host这个代理Service, 到这个address  http://localhost:30096/PassThroughService.svc ,此时你查询的WDSL是这样的:

   1:  <?xml version="1.0" encoding="utf-8"?>
   2:  <wsdl:definitions name="PassThroughService" targetNamespace="http://tempuri.org/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:tns="http://tempuri.org/" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsap="http://schemas.xmlsoap.org/ws/2004/08/addressing/policy" xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl" xmlns:msc="http://schemas.microsoft.com/ws/2005/12/wsdl/contract" xmlns:wsa10="http://www.w3.org/2005/08/addressing" xmlns:wsx="http://schemas.xmlsoap.org/ws/2004/09/mex" xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata">
   3:    <wsdl:types/>
   4:    <wsdl:portType name="IPassThroughService"/>
   5:    <wsdl:binding name="BasicHttpBinding_IPassThroughService" type="tns:IPassThroughService">
   6:      <soap:binding transport="http://schemas.xmlsoap.org/soap/http"/>
   7:    </wsdl:binding>
   8:    <wsdl:service name="PassThroughService">
   9:      <wsdl:port name="BasicHttpBinding_IPassThroughService" binding="tns:BasicHttpBinding_IPassThroughService">
  10:        <soap:address location="http://localhost:30096/PassThroughService.svc"/>
  11:      </wsdl:port>
  12:    </wsdl:service>
  13:  </wsdl:definitions>


接着我们来看UnitTest:

   1:          [TestMethod]
   2:          public void TestCilentWithProxyMessage()
   3:          {
   4:              using (var myChannelFactory = new ChannelFactory<IMath>(new BasicHttpBinding(), "http://localhost:30096/PassThroughService.svc"))
   5:              {
   6:                  // Create a channel.
   7:                  IMath wcfClient1 = myChannelFactory.CreateChannel();
   8:                  var s = wcfClient1.Add(1, 234);
   9:                  Console.WriteLine(s.ToString());
  10:                  ((IClientChannel)wcfClient1).Close();
  11:                  myChannelFactory.Close();
  12:   
  13:                  //assert
  14:                  Assert.AreEqual(235, s);
  15:              }
  16:          }

你可以DEBUG,在var responseMessag = proxy.ProcessMessage(requestMessage); 代码,可以看到Request与Response Message 文本:

Request:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Header>
    <To s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://localhost:30096/PassThroughService.svc</To>
    <Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://tempuri.org/IMath/Add</Action>
  </s:Header>
  <s:Body>
    <Add xmlns="http://tempuri.org/">
      <A>1</A>
      <B>234</B>
    </Add>
  </s:Body>
</s:Envelope>

Response:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Header />
  <s:Body>
    <AddResponse xmlns="http://tempuri.org/">
      <AddResult>235</AddResult>
    </AddResponse>
  </s:Body>
</s:Envelope>

从这里我们可以看到这是完整的消息包,所以使用这个代理Service,拦截消息体后,还可以做一些其它TASK。例如,存储,过滤等。

希望这篇POST对您开发WCF有帮助。


作者:Petter Liu
出处:http://www.cnblogs.com/wintersun/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
该文章也同时发布在我的独立博客中-Petter Liu Blog

posted on 2011-08-11 14:32  PetterLiu  阅读(1165)  评论(0编辑  收藏  举报