原文地址:
http://www.cnblogs.com/HuiTai/archive/2012/05/11/esay_WCF.html
不多闲话,直接进主题吧!
WCF在4.0版本里有这么一个新的特性没有.svc的文件服务激活。
为了验证这么句话,".svc对于服务激活来说就是起到了这么一个映射的作用",今天就用"Hello Word"来验证它吧!.svc文件在我们建立WCF服务项目的时候VS会自动帮我们创建好(图1);我们也可以把它修改成下面的方式(图2)。
图1.(VS自己创建) 图2.(自己修改的)
为了不偏移今天的主题,我们把图1的形式叫"猫";图2的形式叫"咪"。然后我们可以看看猫咪都是可以说"Hello Word".先来看我们"猫"的形式,也是VS为我们生成的结构:
首先我们来新建一个WCF的服务项目吧!叫IService吧,当我们创建好后,VS会为我们创建好如下图3.的样子。
图3. 好吧!VS果然强大吧,创建好了,但是我现在看着他们的名字不爽,我要给它们从新换个名字,先把IService1.cs改成IService.cs吧!Service1.svc文件改成HelloService.svc吧!咦,在改Service1.svc的文件时候并没有改IService1.cs友好,不错VS是帮我们改了Service1.svc成了HelloService.svc了,如下图4.
图4.现在来看看它到时改了没,我们来打开HelloService.svc文件看看,打开它方式在它上面邮件选择'打开方式'里的"带编码的Web服务编辑器"的方式打开它,来看看它的真面目,如下图5.
图5.原来并不了想象中那么友好,实际上它的内在没给我们修改,然后就需要我们手动来修改它和我们的HelloService.svc文件名字同步了。修改后如下图6.
图6.修改好了,那就开始我们的服务端吧!
由于我也是新学WCF的新人,为了更多新接触WCF和我一样的人,我还想多说几句关于服务端的话,首先服务内容是什么呢?服务内容就是我们的IService.cs文件里定义的契约决定,那就来看看我们IService.cs里的契约吧!
namespace WCF_HelloService { /// <summary> /// 服务的内容是有IService决定 /// </summary> [ServiceContract] public interface IService { [OperationContract] string ServiceMeaasge(); } }
既然是服务端,谁提供服务呢!HelloService.svc在这里的作用就是提供服务,提供服务那肯定就是服务对象了,简单的说吧!服务对象负责具体实现服务,当客户端访问服务时,一个服务对象被创建,相应的方法(契约里规定的)被调用,方法执行的结果放回到客户端。那现在就来看看服务对象HelloService.svc吧!
namespace WCF_HelloService { /// <summary> /// 服务对象 /// </summary> public class HelloService : IService { public string ServiceMeaasge() { return "Hello Word"; } } }
到这里服务端我们就先搞到这里,跑起来看看服务端成功没有。
运行的方法很多,我这里说一个比较简单的方法:直接右键HelloService.svc选择在浏览器查看,结果如下图7.
图7.看来我们服务端是OK的。那什么时候创建服务对象,那就由我们的宿主程序决定,宿主程序就是服务宿主也就是ServiceHost,他在WCF运行时负责创建服务宿主,每个ServiceHost都对应着一个服务,在合适的时候ServiceHost对象会创建服务对象来响应客户端的请求. 那就在创建一个宿主程序,在我们的项目添加一个控制台程序进来,叫ConsoleWCF,首先先给控制台程序引进"ServiceModel",然后在添加我们服务端的服务引用,并且把服务引用的命名空间修改HelloWCF,如下图8.
图8.添加好服务端的引用后,VS后自动给我们项目添加app.config文件,这是我们只需要修改一点配置就可以去写我们的控制台程序了(宿主),当然要说的WCF的配置是最重要的也是有些新人比较头大的,当然这些配置也可用代码实现,哪来看看我们宿主程序的配置吧:
<?xml version="1.0" encoding="utf-8" ?> <configuration> <system.serviceModel> <bindings> <basicHttpBinding> <binding name="BasicHttpBinding_IService" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536" messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered" useDefaultWebProxy="true"> <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384" /> <security mode="None"> <transport clientCredentialType="None" proxyCredentialType="None" realm="" /> <message clientCredentialType="UserName" algorithmSuite="Default" /> </security> </binding> </basicHttpBinding> </bindings> <client> <endpoint address="http://localhost:3823/HelloService.svc" binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IService" contract="HelloWCF.IService" name="BasicHttpBinding_IService" /> </client> <!--这里是为宿主程序的配置(Start)--> <services> <service name="WCF_HelloService.HelloService" behaviorConfiguration="WCF_HelloServiceBehavior" > <host> <baseAddresses> <add baseAddress="http://localhost:8000/WCF_HelloService"/> </baseAddresses> </host> <endpoint address="" binding="basicHttpBinding" contract="WCF_HelloService.IService"></endpoint> <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"></endpoint> </service> </services> <behaviors> <serviceBehaviors> <behavior name="WCF_HelloServiceBehavior"> <serviceMetadata httpGetEnabled="true"/> </behavior> </serviceBehaviors> </behaviors> <!--stop--> </system.serviceModel> </configuration>
配置的地方我有注释明确的说明,就不多解释了:
宿主程序的配置好了,哪来写我们的宿主程序,在宿主程序里我监听了一下配置里添加来自端口8000/WCF_HelloService,先看我们控台的程序吧:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ServiceModel; namespace ConsoleWCF { class Program { static void Main(string[] args) { HelloWCF.ServiceClient Hello = new HelloWCF.ServiceClient(); ServiceHost host = new ServiceHost(typeof(WCF_HelloService.HelloService)); host.Open(); Console.WriteLine("监听服务端的信息是:" + Hello.ServiceMeaasge().ToString()); Console.WriteLine("正在监听终结点:http://localhost:8000/WCF_HelloService"); Console.WriteLine("结束监听"); Console.Read(); } } }
控制台(宿主)写好了,运行起来看看结果吧!方法在我们的控制台程序上右键选择调试里的"启动新的实例",运行的结果如下图9,以及端口8000/WCF_HelloService访问结果图10.
图9
图10. 到这里以传统的"猫"的形式的WCF为你叫出的"Hello Word",嘿嘿!要是又哪里搞错的地方,或者描述不清楚或者有误的地方,还请大家多多指点。
说完以"猫"的形式,那在来看看我们以"咪"的形式。信不信我们的"咪"也能叫"Hello Word",其实大家也都注意了开始为大家展示的"猫""咪"的结构对比,"咪"就是少了一个XXX.svc.cs的文件,而多了一个XXX.cs的文件,所以说变化也就在服务端的文件,那就来慢慢解开这个面纱吧!
这次还是新建一个项目叫 Hello_WCF,还是添加以为服务项目经来,叫Hello.WCFService,进去把我们的契约IService1.cs改成IHelloWcfService.cs,并且给项目里添加一个文件夹叫Hello,如下图11.
图11.(为了方便,我们把图11的红色框中的蓝色文件删除掉,并且给Service1.svc换个新名字叫HelloWcfService.svc)然后我们删除掉HelloWcfService.svc.cs的文件,然后在添加一个HelloWcfService.cs的类文件,为了区分我们把契约文件IHelloWcfService.cs和HelloWcfService.cs都放在Hello文件里,如下图12.
图12.现在来打开HelloWcfService.svc里面看看,是什么东东如下图13:
图13.原来如此,我们需要把红线部分知道我们新加进来的HelloWcfService.cs上,让这个HelloWcfService.svc接纳我们为她新配的伴侣,需要改成如下:
<%@ ServiceHost Language="C#" Debug="true" Service="Hello.WCFService.HelloWcfService" CodeBehind="~/Hello/HelloWcfService.cs" %>
现在改好了,那就定义我们的契约吧!IHelloWcfService.cs:
using System; using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; using System.ServiceModel; using System.ServiceModel.Web; using System.Text; namespace Hello.WCFService { [ServiceContract] public interface IHelloWcfService { [OperationContract] string GetServiceMessage(); } }
来用我们新建HelloWcfService.cs的文件继承契约文件,并且实现它吧!
using System; using System.Collections.Generic; using System.Linq; using System.Web; using Hello.WCFService; namespace Hello.WCFService { public class HelloWcfService : IHelloWcfService { public string GetServiceMessage() { return "Hello Word"; } } }
按照以前的做法,到这里我们就OK了,但是由于我们修改他的文件,所以我们还要修改他们的配置文件,为了更好的使用到元数据:
先来看看它未被修改之前的配置,如下图14.
图14.
我们需要修改它成下面的形式:
<?xml version="1.0" encoding="utf-8"?> <configuration> <system.web> <compilation debug="true" targetFramework="4.0" /> </system.web> <system.serviceModel> <services> <service behaviorConfiguration="HelloWcfServiceBehavior" name="Hello.WCFService.HelloWcfService"> <endpoint address="" binding="wsHttpBinding" contract="Hello.WCFService.IHelloWcfService"> <identity> <dns value="localhost"/> </identity> </endpoint> <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"></endpoint> </service> </services> <behaviors> <serviceBehaviors> <behavior name="HelloWcfServiceBehavior"> <serviceMetadata httpGetEnabled="true"/> <serviceDebug includeExceptionDetailInFaults="false"/> </behavior> </serviceBehaviors> </behaviors> </system.serviceModel> </configuration>
修改好配置,来跑跑我们配置的服务吧!(注意使用自己修改文件的方式一定要注意命名空间,要是出错,先检查自己代码的命名空间)。来看下结果吧!如下图15.
图15.到这里是不是有点眼熟,呵呵说明我们的服务已经OK了!接下来需要一个宿主程序来监听我们服务了,接下来给项目搭建一个控制台程序,方法同上,就叫HelloWcf,控制台程序如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace HelloWcf { class Program { static void Main(string[] args) { HelloWCF.HelloWcfServiceClient Hello = new HelloWCF.HelloWcfServiceClient(); Console.WriteLine("从服务器端口下来的信息:"); Console.WriteLine(Hello.GetServiceMessage()); Console.ReadLine(); } } }
来看看结果如下图16:
图16.可以发现这次并没有在宿主这边经行配置,这就是"咪"形式,因为在服务端经行了配置,我们在引用服务端的时候,他们为我们自动添加app.config文件里已经添加进来我们原本需要手动的配置.可以看下配置如下:
<?xml version="1.0" encoding="utf-8" ?> <configuration> <system.serviceModel> <bindings> <wsHttpBinding> <binding name="WSHttpBinding_IHelloWcfService" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard" maxBufferPoolSize="524288" maxReceivedMessageSize="65536" messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true" allowCookies="false"> <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384" /> <reliableSession ordered="true" inactivityTimeout="00:10:00" enabled="false" /> <security mode="Message"> <transport clientCredentialType="Windows" proxyCredentialType="None" realm="" /> <message clientCredentialType="Windows" negotiateServiceCredential="true" algorithmSuite="Default" /> </security> </binding> </wsHttpBinding> </bindings> <client> <endpoint address="http://localhost:6332/HelloWcfService.svc" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IHelloWcfService" contract="HelloWCF.IHelloWcfService" name="WSHttpBinding_IHelloWcfService"> <identity> <dns value="localhost" /> </identity> </endpoint> </client> </system.serviceModel> </configuration>
呵呵!我们"咪"也叫出了"Hello Word",本人理解有限,要是那里错了,还请各位多多指导,在此特谢下明哥指导!
其实对于新手来说WCF的配置有时会显得有点麻烦,其实在宿主程序那里我们的配置也可以用代码完成,就拿上面的"猫"结构的宿主,我们也可以使用下面的方式去实现:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ServiceModel; using WCF_HelloService; namespace ConsoleWCF { class Program { static void Main(string[] args) { HelloService.ServiceClient Hello = new HelloService.ServiceClient(); ServiceHost host = new ServiceHost(typeof(WCF_HelloService.HelloService), new Uri("Http://localhost:8000/WCF_HelloService")); host.AddServiceEndpoint(typeof(IService), new BasicHttpBinding(), ""); host.Open(); Console.WriteLine("监听服务端的信息是:" + Hello.ServiceMeaasge().ToString()); Console.WriteLine("监听的终结点:Http://localhost:8000/WCF_HelloService"); Console.WriteLine("结束监听"); Console.Read(); } } }
上面这种写法,就可以不用去配置,但是看起来还是感觉配置的好,不用写这么多代码,那里看看运行的结果呗如图17:
图17.不想写配置就这么麻烦的写代码也是可以实现的。
今天也就分享这么一点小玩意吧!希望对新手有所帮助,博客上要是存在什么不对的地方还请大家多多指正哦!很感谢明哥的指导哦!