更新时间:2009-01-06
服务契约(Service Contracts)
ServiceContract– 定义服务操作
应用于接口或者类中,并使用接口(或类)上的 ServiceContractAttribute 属性定义服务协定。
• 建议应用于接口中
– 消除服务实现的耦合性
– 服务可能会实现多于1个契约,也就是说方便一个类的实现可以继承于多个服务契约的接口。如果将契约置于具体类上,那就不能实现继承多个契约,受制于c#类的单继承
MSDN备注:使用 ServiceContractAttribute 修饰的接口或类还必须至少拥有一个用 OperationContractAttribute 属性标记的方法以公开任意功能。
• Name,指定 WSDL <portType> 元素中的协定名称。
• Namespace,指定 WSDL <portType> 元素中的命名空间。
• SessionMode,指定协定是否需要支持会话的绑定。
• ConfigurationName,指定要使用的配置文件中的服务元素的名称。
• CallbackContract,指定双向(双工)对话中的返回协定。
• HasProtectionLevel 和ProtectionLevel,指示是否所有支持协定的消息都具有一个显式 ProtectionLevel 值,如果有,处于什么级别。
-------------------------------------解决方案------------------------------------------------------
-------------------------------------服务契约------------------------------------------------------
/// <summary> /// 人员管理接口 /// </summary> // Namespace - 服务契约的命名空间,在WSDL中体现。 // Name - 服务契约的名称,在WSDL中体现。 // ConfigurationName - 服务契约在宿主中所配置的服务名称(默认情况下本例为类的全名“TZOT.WCF.Contract.IPersonManagerService”) [ServiceContract(Namespace="http://www.cnblogs.com/netlife", Name="PersonManager", ConfigurationName="PersonManagerConfig")] public interface IPersonManagerService { /// <summary> /// 获取某人的姓名 /// </summary> /// <param name="person">Person对象</param> /// <returns>对应的名字</returns> // Name - 操作契约的名称(会对应到相关的wsdl,默认情况下本例为方法名“GetName”) [OperationContract(Name = "GetPersonName")] string GetName(Person person); }
-------------------------------------数据契约------------------------------------------------------
/// <summary> /// Person的实体类 /// </summary> // Name - 数据契约的名称(会对应到相关的wsdl,默认情况下本例为类名“Person”) [DataContract(Name = "PersonModel")] public class Person { /// <summary> /// Person的实体类的Age属性 /// </summary> // Name - 数据成员的名称(会对应到相关的wsdl,默认情况下本例为属性名“Age”) // IsRequired - 该值指示序列化引擎该成员在读取或反序列化时必须存在 // Order - 数据成员在相关的wsdl中的顺序 // EmitDefaultValue - 如果应该在序列化流中生成成员的默认值,则为 true,否则为 false,默认值为 true [DataMember(Name = "PersonAge", IsRequired = false, Order = 1)] public int Age { get; set; } /// <summary> /// Person的实体类的Name属性 /// </summary> // Name - 数据成员的名称(会对应到相关的wsdl,默认情况下本例为属性名“Name”) // IsRequired - 该值指示序列化引擎该成员在读取或反序列化时必须存在 // Order - 数据成员在相关的wsdl中的顺序 // EmitDefaultValue - 如果应该在序列化流中生成成员的默认值,则为 true,否则为 false,默认值为 true [DataMember(Name = "PersonName", IsRequired = false, Order = 0)] public string Name { get; set; } }
-------------------------------------Hosting App.Config------------------------------------------------------
<system.serviceModel> <behaviors> <serviceBehaviors> <behavior name="serviceBehavior"> <serviceMetadata httpGetEnabled="true" httpGetUrl=""/> </behavior> </serviceBehaviors> </behaviors> <services> <service name="TZOT.WCF.BusinessServices.PersonManagerService" behaviorConfiguration="serviceBehavior"> <endpoint address="" contract="PersonManagerConfig" binding="basicHttpBinding"/> <!--contract= 是服务契约中配置的ConfigurationName “PersonManagerConfig”,为我们在服务契约中配置的代码。--> <endpoint contract="IMetadataExchange" binding="mexHttpBinding" address="mex" /> <host> <baseAddresses> <add baseAddress="http://localhost:8000/PersonManagerService/" /> </baseAddresses> </host> </service> </services> </system.serviceModel>
-------------------------------------启动服务------------------------------------------------------
class Program { static void Main(string[] args) { //提供服务的主机 ServiceHost personManagerServiceHosting = null; try { personManagerServiceHosting = new ServiceHost(typeof(PersonManagerService)); personManagerServiceHosting.Open(); Console.WriteLine(); Console.WriteLine("Press <ENTER> to terminate Host"); Console.ReadLine(); } finally { personManagerServiceHosting.Close(); } } }
-------------------------------------客户端App.Config------------------------------------------------------
<client> <endpoint address="http://localhost:8000/PersonManagerService/" binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_PersonManager" contract="PersonManagerSerivceRefrence.PersonManager" name="BasicHttpBinding_PersonManager" /> </client>
-------------------------------------客户端添加服务自动生成的部分代码------------------------------------------------------
可以发现自动生成的接口名字为“PersonManager ”,即在服务契约中Name="PersonManager"的体现。
可以发现自动生成的命名空间为Namespace=http://www.cnblogs.com/netlife。
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")] [System.ServiceModel.ServiceContractAttribute(Namespace="http://www.cnblogs.com/netlife", ConfigurationName="PersonManagerSerivceRefrence.PersonManager")] public interface PersonManager { [System.ServiceModel.OperationContractAttribute(Action="http://www.cnblogs.com/netlife/PersonManager/GetPersonName", ReplyAction="http://www.cnblogs.com/netlife/PersonManager/GetPersonNameResponse")] string GetPersonName(TZOT.WCF.Client.PersonManagerSerivceRefrence.PersonModel person); }