WCF系列教程之WCF客户端调用服务
1、创建WCF客户端应用程序需要执行下列步骤
(1)、获取服务终结点的服务协定、绑定以及地址信息
(2)、使用该信息创建WCF客户端
(3)、调用操作
(4)、关闭WCF客户端对象
二、操作实例

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 = , Name = "张三", Age = , Nationality = "China" });
Users.Add(new User { ID = , Name = "李四", Age = , Nationality = "English" });
Users.Add(new User { ID = , Name = "王五", Age = , 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

服务开启成功!
2、新建名为Client的客户端控制台程序,通过添加引用的方式生成WCF客户端

确保Host.exe正常开启的情况下,添加对服务终结点地址http://localhost:6666/UserInfo/的引用,,设置服务命名空间为UserInfoClientNS

点击确定完成添加,生成客户端代理类和配置文件代码后,

开始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=;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();
} }
}

ok,第一种客户端添加引用的方式测试成功
3、新建名为Client1的客户端控制台程序,通过svcutil.exe工具生成客户端代理类的方式生成WCF客户端,在VS2012 开发人员命令提示中输入以下命令:
(1)、定位到当前客户端所在的盘符
(2)、定位当前客户端所在的路径
(3)、svcutil http://localhost:8000/OneWay/?wsdl /o:OneWay.cs 这里是OneWay,你本地是什么就是什么
(4)、生成客户端代理类,生成成功之后,将文件添加到项目中

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 = ; 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();

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 = ; 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();
}
}
}

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系列教程之WCF客户端调用服务的更多相关文章
- WCF系列教程之WCF服务协定
本文参考自:http://www.cnblogs.com/wangweimutou/p/4422883.html,纯属读书笔记,加深记忆 一.服务协定简介: 1.WCF所有的服务协定层里面的服务接口, ...
- WCF系列教程之WCF服务宿主与WCF服务部署
本文参考自http://www.cnblogs.com/wangweimutou/p/4377062.html,纯属读书笔记,加深记忆. 一.简介 任何一个程序的运行都需要依赖一个确定的进程中,WCF ...
- WCF系列教程之WCF服务配置工具
本文参考自http://www.cnblogs.com/wangweimutou/p/4367905.html Visual studio 针对服务配置提供了一个可视化的配置界面(Microsoft ...
- WCF系列教程之WCF服务配置
文本参考自:http://www.cnblogs.com/wangweimutou/p/4365260.html 简介:WCF作为分布式开发的基础框架,在定义服务以及消费服务的客户端时可以通过配置文件 ...
- WCF系列教程之WCF消息交换模式之单项模式
1.使用WCF单项模式须知 (1).WCF服务端接受客户端的请求,但是不会对客户端进行回复 (2).使用单项模式的服务端接口,不能包含ref或者out类型的参数,至于为什么,请参考C# ref与out ...
- WCF系列教程之WCF实例化
本文参考自http://www.cnblogs.com/wangweimutou/p/4517951.html,纯属读书笔记,加深记忆 一.理解WCF实例化机制 1.WCF实例化,是指对用户定义的服务 ...
- WCF系列教程之WCF中的会话
本文参考自http://www.cnblogs.com/wangweimutou/p/4516224.html,纯属读书笔记,加深记忆 一.WCF会话简介 1.在WCF应用程序中,回话将一组消息相互关 ...
- WCF系列教程之WCF客户端异常处理
本文参考自:http://www.cnblogs.com/wangweimutou/p/4414393.html,纯属读书笔记,加深记忆 一.简介 当我们打开WCF基础客户通道,无论是显示打开还是通过 ...
- WCF系列教程之WCF操作协定
一.简介 1.在定义服务协定时,在它的操作方法上都会加上OperationContract特性,此特性属于OperationContractAttribute 类,将OperationContract ...
随机推荐
- 20155316 2016-2017-2 《Java程序设计》第6周学习总结
教材学习内容总结 IO操作的目标 从数据源当中读取数据,以及将数据写入到数据目的地当中: I/O的来源地与目的地多种多样 I/O的流向:输入流.输出流.参照物 IO的分类方法 输入流\输出流: 字节流 ...
- malloc.c
glibc-2.14中的malloc.c源代码,供研究malloc和free实现使用: /* Malloc implementation for multiple threads without lo ...
- Xcode6制作动态及静态Framework[repost]
有没有写SDK或者要将一些常用的工具类做成Framework的经历? 你或许自己写脚本完成了这项工作,相信也有很多的人使用 iOS-Universal-Framework ,随着xCode6的发布,相 ...
- D3 datum()
datum()和data()功能类似. datum():将指定数据赋值给被选择元素.data():将数据数组与选择集的元素结合. var p = d3.selectAll('p'); p.datum( ...
- [ThinkPHP] 比较标签 neq&nheq 与 PHP 中的 != 与 !== 出现的问题
1. 模板 > 内置标签 > 比较标签 控制器: $_data['list'] = [ 'dingo' , 'engo' , 'fengo' , 'gingo' , 'autoFill'= ...
- [label][Chrome-Extension] How to start Chrome Extension's development
Firstly , you should read these two pages. https://developer.chrome.com/extensions/overview https:/ ...
- Java Web系列:JDBC 基础
ADO.NET在Java中的对应技术是JDBC,企业库DataAccessApplicationBlock模块在Java中的对应是spring-jdbc模块,EntityFramework在Java中 ...
- java写入换行符
写入一个文件,生成文本文档,里面写入1000行字符,但是写出来的没有换行.所以纠结,百度了下,一行完事. String crlf=System.getProperty("line.separ ...
- BFC开启条件
当元素CSS属性设置了下列之一时,即可创建一个BFC: float:left|right position:absolute|fixed display: table-cell|table-capti ...
- 【转】Android EventBus初探
出处:http://blog.csdn.net/lmj623565791/article/details/40794879 1.概述 最近大家面试说经常被问到EventBus,github上果断dow ...