首先先要写一个wcf程序,肯定是有一个需求,这个需求我们可以看成一个service,所以我们要建一个wcfservice工程:
using System; using System.ServiceModel; namespace HelloIndigo { //ServiceContract——服务契约,可以用以接口和类,用以接口需要自定义类实现,Namespace是这个服务的域名空间。 [ServiceContract(Namespace="http://www.monkeyfu.net")] public interface IHelloIndigoService { [OperationContract ] string HelloIndigo(string message); } public class HelloIndigoService : IHelloIndigoService { #region IHelloIndigoService Members public string HelloIndigo(string message) { return string.Format("Receivied message at{0}:{1}", DateTime.Now, message); } #endregion } }
详细工程事例:
[ServiceContract(Name = "GigManagerServiceContract", Namespace = "http://www.localhost.com/samples/2006/06", SessionMode = SessionMode.Required)] public interface IGigManagerService { [OperationContract(Name="SaveGig", Action="http://www.localhost.com/samples/2006/06/GigManagerServiceContract/SaveGig", ReplyAction="http://www.thatindigogirl.com/samples/2006/06/GigManagerServiceContract/SaveGigResponse")] void SaveGig([MessageParameter(Name=”LinkItem”)]LinkItem item); [OperationContract(Name="GetGig", Action="http://www.localhost.com/samples/2006/06/GigManagerServiceContract/GetGig", ReplyAction="http://www.thatindigogirl.com/samples/2006/06/GigManagerServiceContract/GetGigResponse")] LinkItem GetGig(); } [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)] public class GigManagerService : IGigManagerService { }
ServiceContractAttribute 可用于接口与类
我们最好用服务契约(ServiceContractAttribute)来定义接口(Interface)。
ServiceContract 属性:
-
Name 自定义接口或方法的名称
-
Namespace 自定义命名空间
-
SessionMode 设置服务契约的 Session 方式,包括 Allowe、NotAllowed、Required。SessionMode 需要相应的 Binding 支持,默认情况下会自动启用,另外我们还会和 ServiceBehaviorAttribute.InstanceContextMode 配合使用来管理服务对象的生命周期。
-
CallbackContract:设置 duplex 模式时的回调类型。
- ProtectionLevel:指定消息保护方式,可以对消息进行加密和签名处理。
- ConfigurationName: 其设置信息在配置文件中的名称。
OperationContract属性:
- AsyncPattern:用于定义异步服务方法。
- IsInitiating:指示服务方法能否启动一个 Session。
- IsTerminating:指示服务方法调用完成是否结束 Session。
- Action: Web调用地址
- ReplyAction :调用后回传的地址
[MessageParameter(Name=”LinkItem”)] /[RetrunMessageParameter(Name=”LinkItem”)] :自定义参数或返回名称名称,映射.
[ServiceContract]:定义服务操作,对于某个Interface加上这个属性标签就会就定义了一个服务,客户端才可以看到这个服务。这个属性标签可以应用于接口或者类,建议应用于接口,第一,可以消除服务实现的耦合性,因为接口中不存在任何的业务逻辑相关的东西,第二,服务可能会实现多于一个契约,也就是说一个类同时实现多个服务,如果把标签定义在类上,就无法同时实现多个服务了。
两个属性:
Name:指定暴露给客户端的服务名称。
Namespace:提供有意义的命名空间。
[OperationContract]:使得方法作为公共服务契约的一部分暴露出来,也就说说客户端可以看到服务中暴露出来的方法。服务契约中的所有方法都应该拥有这个属性标签。
一些属性:
Namespace:提供有意义的命名空间。
Name:指定暴露给客户端的方法名称。
Action:Web调用地址,获取或设置请求消息的 WS-Addressing 操作,定义具体的动作,他表示的是一个层次上的关系,下面的代码中可以看出,Action=namespace+servername+methodname。当客户端导入一个服务终结点的元数据时,如果该终结点的契约属于接口层级的一部分,则生成的客户端契约将不再维持原来的层级关系。相反,它会取消层级,组成一个单独的契约,名称为终结点的契约名。这个单独的契约包含了层级中从上至下所有接口定义的操作。然而,如果使用OperationContract特性中的Action
ResponseAction属性,那么导入的接口定义仍然可以保留原来定义每个操作的契约名,比如:服务接口之间如果有继承关系的存在,那么他就可以派上用场了。
ReplyAction:调用后回传的地址,获取或设置用于该操作答复消息的 SOAP 操作的值,定义具体的相应动作。它主要完成的是SOAP数据到具体代码的映射关系。
[MessageParameter]:用来控制参数或者返回名称,映射作用。具体如下:有一个Java的客户端,发送一个SOAP给WCF服务,WCF会检查SOAP中有没有的对应定义的MessageParameter Name,如果有就会对应到WCF函数中的相应位置,通过这种映射关系,然后通过反序列化把数据传到WCF的对应方法中,实现对象的传递。
概念SOAP:Simple Object Access Protocol,简单对象访问协议(SOAP)是一种轻量的、简单的、基于 XML 的协议,它被设计成在 WEB 上交换结构化的和固化的信息。 SOAP 可以和现存的许多因特网协议和格式结合使用,包括超文本传输协议( HTTP),简单邮件传输协议(SMTP),多用途网际邮件扩充协议(MIME)。它还支持从消息系统到远程过程调用(RPC)等大量的应用程序。
WCF服务和Client之间其实就是用的SOAP这种协议。
接下来我们可以写一个wcf服务器端的代码
using System; using System.Collections.Generic; using System.Text; using System.ServiceModel; using System.ServiceModel.Dispatcher; namespace Host { class Program { static void Main(string[] args) { using (ServiceHost host = new ServiceHost(typeof(HelloIndigo.HelloIndigoService))) { host.AddServiceEndpoint(typeof(HelloIndigo.IHelloIndigoService), new NetTcpBinding(), "net.tcp://localhost:9000/HelloIndigo"); host.Open(); Console.ReadLine(); } } } }
wcf主机host可以手动写代码如上,也可以用配置的形式——app.config:
<?xml version="1.0" encoding="utf-8" ?> <configuration> <system.serviceModel> <services> <service name="HelloIndigo.HelloIndigoService" behaviorConfiguration="serviceBehavior"> <endpoint binding="basicHttpBinding" contract="HelloIndigo.IHelloIndigoService" address="HelloIndigo" /> <endpoint binding="mexHttpBinding" contract="IMetadataExchange" address="mex" /> <host> <baseAddresses> <add baseAddress="http://localhost:8000"/> </baseAddresses> </host> </service> </services> <behaviors> <serviceBehaviors> <behavior name="serviceBehavior"> <serviceMetadata httpGetEnabled="true" /> </behavior> </serviceBehaviors> </behaviors> </system.serviceModel> </configuration>
主机端写完最后可以生产客户端的代码。
using System; using System.Collections.Generic; using System.Text; using System.ServiceModel; namespace Client { [ServiceContract(Namespace = "http://www.monkeyfu.net")] public interface IHelloIndigoService { [OperationContract] string HelloIndigo(string message); } class Program { static void Main(string[] args) { IHelloIndigoService proxy = ChannelFactory<IHelloIndigoService>.CreateChannel(new NetTcpBinding(), new EndpointAddress("net.tcp://localhost:9000/HelloIndigo")); //localhost.HelloIndigoServiceClient proxy = new Client.localhost.HelloIndigoServiceClient(); string s = proxy.HelloIndigo("Hello from client..."); Console.WriteLine(s); Console.ReadLine(); } } }
客户端首先根据服务契约的域名空间生成一个代理类IHelloIndigoService,通过这个代理类我们可以生产客户端的proxy(<IHelloIndigoService>:服务契约,new NetTcpBinding():绑定的传输方式,new EndpointAddress("net.tcp://localhost:9000/HelloIndigo"生成一个endpoint) ,通过proxy我们就可以完成相应的服务逻辑代码了。