自强不息,厚德载物!身心自在,道法自然!


HelloWord之WCF文件的猫咪形式

不多闲话,直接进主题吧!

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里的契约吧!

View Code
namespace WCF_HelloService
{
     /// <summary>
     /// 服务的内容是有IService决定
    /// </summary>
    [ServiceContract]
    public interface IService
    {
        [OperationContract]
        string ServiceMeaasge();
    }
}

既然是服务端,谁提供服务呢!HelloService.svc在这里的作用就是提供服务,提供服务那肯定就是服务对象了,简单的说吧!服务对象负责具体实现服务,当客户端访问服务时,一个服务对象被创建,相应的方法(契约里规定的)被调用,方法执行的结果放回到客户端。那现在就来看看服务对象HelloService.svc吧!

View Code
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的配置是最重要的也是有些新人比较头大的,当然这些配置也可用代码实现,哪来看看我们宿主程序的配置吧:

View Code
<?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,先看我们控台的程序吧:

View Code
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:

View Code
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的文件继承契约文件,并且实现它吧!

View Code
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.

我们需要修改它成下面的形式:

View Code
<?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,控制台程序如下:

View Code
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的配置有时会显得有点麻烦,其实在宿主程序那里我们的配置也可以用代码完成,就拿上面的"猫"结构的宿主,我们也可以使用下面的方式去实现:

View Code
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.不想写配置就这么麻烦的写代码也是可以实现的。

今天也就分享这么一点小玩意吧!希望对新手有所帮助,博客上要是存在什么不对的地方还请大家多多指正哦!很感谢明哥的指导哦!

posted @ 2012-05-11 23:40  辉太  阅读(2054)  评论(2编辑  收藏  举报

路漫漫其修远兮,吾将上下而求索!