从刚开始学习C#时就听说了WCF,然而直至上星期对WCF还只是停留在知道WCF是Windows Communication Foundation的缩写上,上星期刚开始熟悉新项目的框架,感觉跟着框架进行开发还是傻瓜式的,不学习原理那开发就真是重复劳动了,只是进行一个个业务逻辑的编程。
学习了几天,参考了两本书和好些前辈大牛们的博客,还有自己的测试练习。感觉也只是将HelloWorld稍微研究懂了点,当然也遇到了不少挫折,根据个人的理解将HelloWorld总结出来并提供源码,源码的例子自认为是方便易懂的,一方面给后来者参考,一方面也给自己以记录。
首先先看一个例子(来自博客园,作者昵称:翼帆,看到这篇文章也偶然,是我一同事的qq中的个人说明中记录的网页,我就点开看了一下),博客网址。讲的是客户端调用微软为开发者公开的服务接口。微软的翻译服务在那,对于全球各地的客户端,只要引用该服务就可以调用翻译服务接口为自己进行翻译操作。从这个例子能够直观的看到客户端怎样简单调用服务。具体操作见原例子。简单的说就是服务端与客户端的通信,上面的例子就是已经有了服务端,然后自己引用服务,手写客户端的例子。
对于服务端,每个服务终结点包括三要素:地址、绑定和契约。具体如下:
地址:在WCF中,每个服务都有惟一的地址。
绑定:定义服务和客户端通信的方式。
契约:属于服务公开接口的一部分,告诉其他节点这个服务是干什么的。
服务必须先开启,客户端才能调用服务。
下面开始第一个Hello World例子(完全手动的创建服务)。
新建一个空项目。
第一步:建立契约(建立一个类库)
添加.net引用System.ServiceModel,定义一个接口,在接口上加特性【ServiceContract】,在放入服务的方法上加上特性【OperationContract】,如下:
[ServiceContract]
public interface IService
{
[OperationContract]
string Greetings(string name);
}
第二步:实现服务契约(建立一个类库)
public class Service:IService
{
public string Greetings(string name)
{
return name + " Say : Hello World!";
}
}
第三步:建立宿主(新建一个控制台应用程序)
//初始化ServiceHost对象(用实现服务的类型和基地址初始化)
//提供服务的主机
ServiceHost host = new ServiceHost(typeClassService, new Uri[] { new Uri(baseAddress) });
//添加一个终结点,包括(服务契约类型,服务定义的绑定,服务地址)
host.AddServiceEndpoint(typeInterfaceService, HelloWorldBinding, helloWorldServiceAddress);
//启动服务
host.Open();
Console.WriteLine("Service is started!");
Console.WriteLine("Press any key to stop the service!");
Console.Read();
其中Type typeInterfaceService = typeof(IService); //服务契约定义类型
Type typeClassService = typeof(Service); //服务契约实现类型
string baseAddress = "net.pipe://localhost";//基地址(注意写法)
string helloWorldServiceAddress = "HelloWorld";//可选地址
Binding HelloWorldBinding = new NetNamedPipeBinding();//服务只定义了一个绑定
至此服务器端已经完毕
第四步:客户端
public class Hello : ClientBase<IService>, IService
{
public static Binding HelloWorldBinding = new NetNamedPipeBinding();
public static EndpointAddress HelloWorldAddress = new EndpointAddress(new Uri("net.pipe://localhost/HelloWorld"));
public Hello() : base(HelloWorldBinding, HelloWorldAddress) { }
public string Greetings(string name)
{
return Channel.Greetings(name);
}
}
然后在入口方法中调用
static void Main(string[] args)
{
using (Hello hello = new Hello())
{
string msg = hello.Greetings("pfe_Nova");
Console.WriteLine(msg);
Console.Read();
}
}
至此就好了,将Host设为启动项目,运行后,右键点击Client调试启动新实例,然后就可以在同一个项目中既运行服务端又运行客户端。
第二种方法是应用配置文件实现。
首先还是先建一个空项目,先建两个类库,一个写契约,一个写契约的实现,代码跟上例一样。
第三步新建控制台应用程序,名为Host0225,添加配置文件
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="metadataBehavior">
<serviceMetadata httpGetEnabled="true"
httpGetUrl="http://127.0.0.1:8888/Service/metadata" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="Service0225.Service" behaviorConfiguration="metadataBehavior">
<endpoint address="http://127.0.0.1:8888/Service"
binding="wsHttpBinding"
contract="IService0225.IService" >
</endpoint>
</service>
</services>
</system.serviceModel>
</configuration>
添加引用:契约引用,契约实现的引用,System. ServiceModel引用
在入口函数中写
static void Main(string[] args)
{
using (ServiceHost host = new ServiceHost(typeof(Service)))
{
host.Open();
Console.WriteLine("Service is started! ");
Console.WriteLine("Press any key to stop the service! ");
Console.Read();
}
}
如此,系统会自动调用配置文件中的配置信息,而无需考虑具体如何实现(当然了,学习后期得研究)。
第四步:编译Host0225,找到其可执行文件,运行。
第五步:新建控制台应用程序,名为Client0225,右键Client0225添加服务引用
在地址中输入:http://127.0.0.1:8888/Service/metadata(在host0225配置文件中有)
如此便有了服务器端的服务,同时会自动生成相应配置文件。
添加引用System.ServiceModel,System.ServiceModel.Channels以及服务引用using Client0225.Service2012;在主函数入口编写
using (Service2012.ServiceClient Client=new ServiceClient ())
{
Console.WriteLine(Client.Greetings("pf"));
Console.Read();
}
第六步: 将Host0225设为启动项目,运行后,右键点击Client调试启动新实例,然后就可以在同一个项目中既运行服务端又运行客户端。
第三种方法,直接建立WCF应用程序
首先建立一个空解决方案
其次建立一个WCF服务应用程序,这里命名为Service0304,然后自动就生成相应的代码,将接口改为IService,点击Service1.svc文件,然后使用“重构”菜单上的“重命 名”命令将Service1改为Service,(注:这两个改名操作本没有什么实际意义,只是本人不喜欢这种命名),至此服务端的代码就好了,几乎什么也没干。
最后新建一个控制台应用程序,命名为Client0304,右键Client0304添加服务引用点击“发现”,然后改一下命名空间,服务就添加上了。
然后在入口函数中测试。
Service2012.ServiceClient client = new Service2012.ServiceClient();
string msg=client.GetData(2012);
Console.WriteLine(msg);
后记:本来初稿25就写出来了,虽然技术含量并不高,但作为初学者,写的过程还是收获到不少。以前我写这类关于服务器与客户端的例子时都是随便写,也不去考虑文件的管理,服务端和客户端都是在两个解决方案里,看了博客园Artech 的WCF系列文章后发现,原来写在一个解决方案里更好管理,再看评论发现还可以同时打开(我以前写Socket例子都是找到可执行文件一个一个点开)。其次关于更新服务的问题,我刚开始写了个例子然后我改了配置文件,没有更新服务,发现结果是一样的,于是我就认为两种写法效果一样,但写博客时我又重新写例子的,这次怎么也添加不上服务,感觉一模一样,百思不得其解。后来我干脆将原来的代码都复制到一个新的项目中,发现还是不行,问了我们项目组一前辈,我让他看,为什么这个行,另一个不行,他当时看了会也没看出什么异样(我问问题的方式干扰了他的思维方向)。放了几天最后发现是没有更新服务,错误的配置文件缺少一个属性。