WCF系列教程之WCF客户端调用服务
2017-05-15 23:29
751 查看
1、创建WCF客户端应用程序需要执行下列步骤
(1)、获取服务终结点的服务协定、绑定以及地址信息
(2)、使用该信息创建WCF客户端
(3)、调用操作
(4)、关闭WCF客户端对象
二、操作实例
![](https://oscdn.geek-share.com/Uploads/Images/Content/201911/26/1f74fa1d2003100ffde88a4a0c9dded5.png)
1、WCF服务层搭建:新建契约层、服务层、和WCF宿主,添加必须的引用(这里不会的参考本人前面的随笔),配置宿主,生成解决方案,打开Host.exe,开启服务。具体的代码如下:
ICalculate.cs
IUserInfo.cs
注:必须引入System.Runtime.Serialization命名空间,应为User类在被传输时必须是可序列化的,否则将无法传输
Calculate.cs
UserInfo.cs
Program.cs
App.Config
ok,打开Host.exe
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/18/a1be5b3b53203f3937fef60fc565518d.png)
服务开启成功!
2、新建名为Client的客户端控制台程序,通过添加引用的方式生成WCF客户端
![](https://oscdn.geek-share.com/Uploads/Images/Content/201911/26/0754417374d1c1a1b2724aa4fc563168.png)
确保Host.exe正常开启的情况下,添加对服务终结点地址http://localhost:6666/UserInfo/的引用,,设置服务命名空间为UserInfoClientNS
![](https://oscdn.geek-share.com/Uploads/Images/Content/201911/26/91162febed0d6bb84d0526b6e36221ad.png)
点击确定完成添加,生成客户端代理类和配置文件代码后,
![](https://oscdn.geek-share.com/Uploads/Images/Content/201911/26/470e3bf2902d8b3ba3c70a8b64ed781b.png)
开始Client客户端控制台程序对WCF服务的调用,Program.cs代码如下:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201911/26/74845eddb8e0fa00dd74293c6c9f8519.png)
ok,第一种客户端添加引用的方式测试成功
3、新建名为Client1的客户端控制台程序,通过svcutil.exe工具生成客户端代理类的方式生成WCF客户端,在VS2012 开发人员命令提示中输入以下命令:
(1)、定位到当前客户端所在的盘符
![](https://oscdn.geek-share.com/Uploads/Images/Content/201911/26/45728b73dbd077732c0acf614b59f243.png)
(2)、定位当前客户端所在的路径
![](https://oscdn.geek-share.com/Uploads/Images/Content/201911/26/60340a74ee239cbe5d62f349e24b0db1.png)
(3)、svcutil http://localhost:8000/OneWay/?wsdl /o:OneWay.cs 这里是OneWay,你本地是什么就是什么
(4)、生成客户端代理类,生成成功之后,将文件添加到项目中
![](https://oscdn.geek-share.com/Uploads/Images/Content/201911/26/83cb3a03f9570de3f9802399a9cbb3c3.png)
ok,生成成功!
(5)、将生成的文件包括到项目中,引入System.Runtime.Serialization命名空间和System.ServiceModel命名空间
(6)、确保服务开启的情况下,开始调用,Program.cs代码如下:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201911/26/6680029555f852f9487fe9d2b813b056.png)
ok,服务调用成功,说明使用svcutil工具生成WCF客户端的方式可行。
4、通过添加对Service程序集的引用,完成对WCF服务端的调用,新建一个Client2客户端控制台程序
先添加下面三个引用
using IService;
using System.ServiceModel;
using System.ServiceModel.Channels;
(1)、Program.cs代码如下:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201911/26/45755caf5fe5f1eff1bf97bbeafc2824.png)
ok,调用成功!
三、归纳总结
通过上面的代码判断WCF客户端调用服务存在以下特点:
1、WCF服务端可客户端通过使用托管属性、接口、方法对协定进行建模。若要连接到服务端的服务,则需要获取该服务协定的类型信息.获取协定的类型信息有两种方式:
(1)、通过Svcutil工具,在客户端生成代理类的方式,来获取服务端服务的服务协定的类型信息
(2)、通过给项目添加服务引用的方式
上面两种方式都会从服务端的服务中下载元数据,并使用当前你使用的语言,将其转换成托管源代码文件中,同时还创建一个您可用于配置 WCF 客户端对象的客户端应用程序配置文件.
2、WCF客户端是表示某个WCF服务的本地对象,客户端可以通过该本地对象与远程服务进行通信。因此当你在服务端创建了一个服务端协定,并对其进行配置后,客户端就可以通过生成代理类的方式(具体生成代理类的方式,上面已经提了)和服务端的服务进行通信,WCF 运行时将方法调用转换为消息,然后将这些消息发送到服务,侦听回复,并将这些值作为返回值或 out 参数(或 ref 参数)返回到 WCF 客户端对象中.(有待考证);
3、创建并配置了客户端对象后,请创建一个 try/catch 块,如果该对象是本地对象,则以相同的方式调用操作,然后关闭 WCF 客户端对象。 当客户端应用程序调用第一个操作时,WCF 将自动打开基础通道,并在回收对象时关闭基础通道。 (或者,还可以在调用其他操作之前或之后显式打开和关闭该通道。)。不应该使用 using 块来调用WCF服务方法。因为C# 的“using”语句会导致调用 Dispose()。 它等效于 Close(),当发生网络错误时可能会引发异常。 由于对 Dispose() 的调用是在“using”块的右大括号处隐式发生的,因此导致异常的根源往往会被编写代码和阅读代码的人所忽略。 这是应用程序错误的潜在根源
(1)、获取服务终结点的服务协定、绑定以及地址信息
(2)、使用该信息创建WCF客户端
(3)、调用操作
(4)、关闭WCF客户端对象
二、操作实例
![](https://oscdn.geek-share.com/Uploads/Images/Content/201911/26/1f74fa1d2003100ffde88a4a0c9dded5.png)
1、WCF服务层搭建:新建契约层、服务层、和WCF宿主,添加必须的引用(这里不会的参考本人前面的随笔),配置宿主,生成解决方案,打开Host.exe,开启服务。具体的代码如下:
ICalculate.cs
using System; using System.Collections.Generic; using System.Linq; using System.ServiceModel; using System.Text; using System.Threading.Tasks; namespace IService { [ServiceContract] public interface ICalculate { [OperationContract] int Add(int a, int b); } }
IUserInfo.cs
using System; using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; using System.ServiceModel; using System.Text; using System.Threading.Tasks; namespace IService { [ServiceContract] public interface IUserInfo { [OperationContract] User[] GetInfo(int? id); } [DataContract] public class User { [DataMember] public int ID { get; set; } [DataMember] public string Name { get; set; } [DataMember] public int Age { get; set; } [DataMember] public string Nationality { get; set; } } }
注:必须引入System.Runtime.Serialization命名空间,应为User类在被传输时必须是可序列化的,否则将无法传输
Calculate.cs
using IService; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Service { public class Calculate : ICalculate { public int Add(int a, int b) { return a + b; } } }
UserInfo.cs
using IService; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Service { public class UserInfo : IUserInfo { public User[] GetInfo(int? id) { List<User> Users = new List<User>(); Users.Add(new User { ID = 1, Name = "张三", Age = 11, Nationality = "China" }); Users.Add(new User { ID = 2, Name = "李四", Age = 12, Nationality = "English" }); Users.Add(new User { ID = 3, Name = "王五", Age = 13, Nationality = "American" }); if (id != null) { return Users.Where(x => x.ID == id).ToArray(); } else { return Users.ToArray(); } } } }
Program.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using Service; using System.ServiceModel; namespace Host { class Program { static void Main(string[] args) { using (ServiceHost host = new ServiceHost(typeof(Calculate))) { host.Opened += delegate { Console.WriteLine("服务已经启动,按任意键终止!"); }; host.Open(); Console.Read(); } } } }
App.Config
<?xml version="1.0"?> <configuration> <system.serviceModel> <services> <service name="Service.Calculate" behaviorConfiguration="mexBehavior"> <host> <baseAddresses> <add baseAddress="http://localhost:1234/Calculate/"/> </baseAddresses> </host> <endpoint address="" binding="wsHttpBinding" contract="IService.ICalculate" /> <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/> </service> </services> <behaviors> <serviceBehaviors> <behavior name="mexBehavior"> <serviceMetadata httpGetEnabled="true"/> <serviceDebug includeExceptionDetailInFaults="true"/> </behavior> </serviceBehaviors> </behaviors> </system.serviceModel> </configuration>
ok,打开Host.exe
![](https://oscdn.geek-share.com/Uploads/Images/Content/201705/18/a1be5b3b53203f3937fef60fc565518d.png)
服务开启成功!
2、新建名为Client的客户端控制台程序,通过添加引用的方式生成WCF客户端
![](https://oscdn.geek-share.com/Uploads/Images/Content/201911/26/0754417374d1c1a1b2724aa4fc563168.png)
确保Host.exe正常开启的情况下,添加对服务终结点地址http://localhost:6666/UserInfo/的引用,,设置服务命名空间为UserInfoClientNS
![](https://oscdn.geek-share.com/Uploads/Images/Content/201911/26/91162febed0d6bb84d0526b6e36221ad.png)
点击确定完成添加,生成客户端代理类和配置文件代码后,
![](https://oscdn.geek-share.com/Uploads/Images/Content/201911/26/470e3bf2902d8b3ba3c70a8b64ed781b.png)
开始Client客户端控制台程序对WCF服务的调用,Program.cs代码如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Client.UserInfoClientNS; namespace Client { class Program { static void Main(string[] args) { UserInfoClient proxy =new UserInfoClient(); User[] Users = proxy.GetInfo(null); Console.WriteLine("{0,-10}{1,-10}{2,-10}{3,-10}","ID","Name","Age","Nationality"); for(int i=0;i<Users.Length;i++) { Console.WriteLine("{0,-10}{1,-10}{2,-10}{3,-10}", Users[i].ID.ToString(), Users[i].Name.ToString(), Users[i].Age.ToString(), Users[i].Nationality.ToString()); } Console.Read(); } } }
![](https://oscdn.geek-share.com/Uploads/Images/Content/201911/26/74845eddb8e0fa00dd74293c6c9f8519.png)
ok,第一种客户端添加引用的方式测试成功
3、新建名为Client1的客户端控制台程序,通过svcutil.exe工具生成客户端代理类的方式生成WCF客户端,在VS2012 开发人员命令提示中输入以下命令:
(1)、定位到当前客户端所在的盘符
![](https://oscdn.geek-share.com/Uploads/Images/Content/201911/26/45728b73dbd077732c0acf614b59f243.png)
(2)、定位当前客户端所在的路径
![](https://oscdn.geek-share.com/Uploads/Images/Content/201911/26/60340a74ee239cbe5d62f349e24b0db1.png)
(3)、svcutil http://localhost:8000/OneWay/?wsdl /o:OneWay.cs 这里是OneWay,你本地是什么就是什么
(4)、生成客户端代理类,生成成功之后,将文件添加到项目中
![](https://oscdn.geek-share.com/Uploads/Images/Content/201911/26/83cb3a03f9570de3f9802399a9cbb3c3.png)
ok,生成成功!
(5)、将生成的文件包括到项目中,引入System.Runtime.Serialization命名空间和System.ServiceModel命名空间
(6)、确保服务开启的情况下,开始调用,Program.cs代码如下:
UserInfoClient proxy = new UserInfoClient(); User[] Users = proxy.GetInfo(null); Console.WriteLine("{0,-10}{1,-10}{2,-10}{3,-10}", "ID", "Name", "Age", "Nationality"); for (int i = 0; i < Users.Length; i++) { Console.WriteLine("{0,-10}{1,-10}{2,-10}{3,-10}", Users[i].ID.ToString(), Users[i].Name.ToString(), Users[i].Age.ToString(), Users[i].Nationality.ToString()); } Console.Read();
![](https://oscdn.geek-share.com/Uploads/Images/Content/201911/26/6680029555f852f9487fe9d2b813b056.png)
ok,服务调用成功,说明使用svcutil工具生成WCF客户端的方式可行。
4、通过添加对Service程序集的引用,完成对WCF服务端的调用,新建一个Client2客户端控制台程序
先添加下面三个引用
using IService;
using System.ServiceModel;
using System.ServiceModel.Channels;
(1)、Program.cs代码如下:
using System; using System.Collections.Generic; using System.Linq; using IService; using System.ServiceModel; using System.ServiceModel.Channels; using System.Text; using System.Threading.Tasks; namespace Client2 { class Program { static void Main(string[] args) { EndpointAddress address = new EndpointAddress("http://localhost:6666/UserInfo/"); WSHttpBinding binding = new WSHttpBinding(); ChannelFactory<IUserInfo> factory = new ChannelFactory<IUserInfo>(binding, address); IUserInfo channel = factory.CreateChannel(); User[] Users = channel.GetInfo(null); Console.WriteLine("{0,-10}{1,-10}{2,-10}{3,-10}", "ID", "Name", "Age", "Nationality"); for (int i = 0; i < Users.Length; i++) { Console.WriteLine("{0,-10}{1,-10}{2,-10}{3,-10}", Users[i].ID.ToString(), Users[i].Name.ToString(), Users[i].Age.ToString(), Users[i].Nationality.ToString()); } ((IChannel)channel).Close(); factory.Close(); Console.Read(); } } }
![](https://oscdn.geek-share.com/Uploads/Images/Content/201911/26/45755caf5fe5f1eff1bf97bbeafc2824.png)
ok,调用成功!
三、归纳总结
通过上面的代码判断WCF客户端调用服务存在以下特点:
1、WCF服务端可客户端通过使用托管属性、接口、方法对协定进行建模。若要连接到服务端的服务,则需要获取该服务协定的类型信息.获取协定的类型信息有两种方式:
(1)、通过Svcutil工具,在客户端生成代理类的方式,来获取服务端服务的服务协定的类型信息
(2)、通过给项目添加服务引用的方式
上面两种方式都会从服务端的服务中下载元数据,并使用当前你使用的语言,将其转换成托管源代码文件中,同时还创建一个您可用于配置 WCF 客户端对象的客户端应用程序配置文件.
2、WCF客户端是表示某个WCF服务的本地对象,客户端可以通过该本地对象与远程服务进行通信。因此当你在服务端创建了一个服务端协定,并对其进行配置后,客户端就可以通过生成代理类的方式(具体生成代理类的方式,上面已经提了)和服务端的服务进行通信,WCF 运行时将方法调用转换为消息,然后将这些消息发送到服务,侦听回复,并将这些值作为返回值或 out 参数(或 ref 参数)返回到 WCF 客户端对象中.(有待考证);
3、创建并配置了客户端对象后,请创建一个 try/catch 块,如果该对象是本地对象,则以相同的方式调用操作,然后关闭 WCF 客户端对象。 当客户端应用程序调用第一个操作时,WCF 将自动打开基础通道,并在回收对象时关闭基础通道。 (或者,还可以在调用其他操作之前或之后显式打开和关闭该通道。)。不应该使用 using 块来调用WCF服务方法。因为C# 的“using”语句会导致调用 Dispose()。 它等效于 Close(),当发生网络错误时可能会引发异常。 由于对 Dispose() 的调用是在“using”块的右大括号处隐式发生的,因此导致异常的根源往往会被编写代码和阅读代码的人所忽略。 这是应用程序错误的潜在根源
相关文章推荐
- WCF系列教程之客户端异步调用服务
- VS2010 创建WCF以及SL的客户端如何调用WCF服务教程(一): 创建WCF
- VS2010 创建WCF以及SL的客户端如何调用WCF服务 教程(二): 创建调用WCF的SilverLight客户端
- VS2010 创建WCF以及SL的客户端如何调用WCF服务 教程(二): 创建调用WCF的SilverLight客户端
- VS2010 创建WCF以及SL的客户端如何调用WCF服务教程(一): 创建WCF
- VS2010 创建WCF以及SL的客户端如何调用WCF服务教程(一): 创建WCF
- WCF技术剖析之十:调用WCF服务的客户端应该如何进行异常处理(转)
- WCF分布式开发常见错误(3):客户端调用服务出错
- [原创] WCF技术剖析之十:调用WCF服务的客户端应该如何进行异常处理
- WCF 客户端调用服务操作的两种方法
- WCF热门问题编程示例(4):WCF客户端如何异步调用WCF服务?
- 客户端动态调用WCF服务中的方法
- Java与WCF交互(一):Java客户端调用WCF服务
- Invoke WCF service from Java Client with Authentication (X.509 Certificate) Java 客户端调用WCF服务 需要安全验证
- 一步一个脚印学习WCF系列之WCF概要—WCF服务的创建与调用HelloWorld实例,通过编码方式(四)
- Java与WCF交互(一):Java客户端调用WCF服务 (转)
- Java与WCF交互(一):Java客户端调用WCF服务 (转)
- WCF客户端调用服务 出现套接字连接已中止......
- 对硬编码WCF服务的封装(提供服务和客户端调用的封装,调用样例....)
- WCF技术剖析之十:调用WCF服务的客户端应该如何进行异常处理