有时在项目中,由于部署的原因。我们需要对原来的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。