4. 通过配置文件方式实现基于 WCF 服务的 HelloWor

2019-05-13  本文已影响0人  璎珞纨澜

契约与元数据

服务描述和元数据

  1. 生成服务描述
    如图 1,在 ServiceHost 里面运行着服务以及相应的端点,ServiceHost 里面又多了一个东西是 ServiceDescription 服务描述,也就是 Service 具体的描述,由这个 ServiceDescription 将 Service 和 Endpoint 以及相关的 Address、Binding、Contract 信息在这里进行了相应的记录,外面是有一个 Config 文件,当 ServiceHost 启动的时候来加载这个 Config 文件,根据 Config 文件里面具体的内容来生成相应的描述信息。

    图 1
  2. 生成 WSDL
    如图 2,由 ServiceDescription 服务描述来生成 WSDL 的文件,通过 svcutil.exe 这个工具来生成相应的在客户端所使用的这个 Proxy 代理以及相应的代码,同样在客户端我们可以通过 Config 配置文件的方式来影响 Proxy 代理以及 Channel 通道的生成。

    图 2
  3. 元数据的交换
    完成了图 2 阶段后,我们可以通过 svcutil.exe 这个工具来实现从 Service 服务这一端到 Client 客户这一端的数据交换,整个的服务描述与数据的交互就是图 3 的结构,从这个结构图我们可以看到,Client 客户端在获取 Service 服务具体的信息的时候,实际上不会直接与 Service 或者 Endpoint 来进行接触,它是通过 ServiceDescription 服务描述来获得的并且通过元数据交互这种方式来得到相应的信息,然后构建客户端自己的 Proxy 代理。所以,如果我们的 Service 或者 Endpoint 内部的一些逻辑发生变化的话,只要它不影响 ServiceDescription 服务描述,就不会对客户端的 proxy 代理产生影响,也就不会对客户端产生影响。通过这种方式实现了 Client 端和 ServiceHost 端的松耦合关系。

    图 3

通过配置文件方式实现基于 WCF 服务的 HelloWorld 实例

服务相应的代码除了可以通过编码的方式实现的,还可以通过向导来生成。以下操作基于《3. 通过编码方式实现基于 WCF 服务的 HelloWorld 实例》一文中的项目代码。

1. 服务端配置 App.config

在 Host 工程右击 Add -> New Item选择 Application Configuration File,新建一个 App.config 配置文件。

配置文件解释:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    <services>
      <service name="HelloWorldService.HelloWorldService" behaviorConfiguration="serviceBehavior">
        <endpoint address="HelloWorldService" binding="basicHttpBinding" contract="HelloWorldService.IHelloWorldService" />
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:8000"/>
          </baseAddresses>
        </host>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="serviceBehavior">
          <serviceMetadata httpGetEnabled="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>  
</configuration>

2.通过元数据生成代理和配置文件

2.1 保存 Host 这端的配置文件,启动 Host:

注意:HTTP 无法注册 URL http://+:8000/。进程不具有此命名空间的访问权限(有关详细信息,请参见 http://go.microsoft.com/fwlink/?LinkId=70353)。
如按照例子一开始就遇到这样的问题,原因可能是Win 7,解决方法是Visual Studio 以管理员的身份运行就可以了。

图1:host启动
2.2 客户端添加服务引用,自动生成配置文件与代码

在 Client 工程上右击 Add Service Reference,在 Address 栏输入已经开启的服务地址 http://localhost:8000/,点击 Go ,将命名空间改为 Proxy,点击 OK 就添加成功了。

image.png

上述步骤提供了基于Http协议消息的 Host,由Visual Studio会根据WSDL里面的内容来自动生成相应的代理文件以及相应的配置文件。Project -> Show All Files可以看到如下目录。在Reference.svcmap下面有个Reference.cs,在这个Reference.cs里面有由系统自动为我们生成的代理类,在我们进行使用的时候,我们直接使用代理类来进行服务的操作。


image.png

在 Client 端生成了和 Host 端相关的的相应的配置文件以及里面的配置信息和配置参数,对于这些参数可以根据我们具体需求来进行具体的配置如下:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <system.serviceModel>
        <bindings>
            <basicHttpBinding>
                <binding name="BasicHttpBinding_IHelloWorldService" 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>
          
            <!--<netTcpBinding>
                <binding name="NetTcpBinding_IHelloWorldService" />
            </netTcpBinding>-->
        </bindings>
        <client>
            <endpoint address="http://localhost:8000/HelloWorldService" binding="basicHttpBinding"
                bindingConfiguration="BasicHttpBinding_IHelloWorldService"
                contract="Proxy.IHelloWorldService" name="BasicHttpBinding_IHelloWorldService" />
            <!--<endpoint address="net.tcp://localhost:9000/HelloWorldService"
                binding="netTcpBinding" bindingConfiguration="NetTcpBinding_IHelloWorldService"
                contract="Proxy.IHelloWorldService" name="NetTcpBinding_IHelloWorldService">
            </endpoint>-->
        </client>
    </system.serviceModel>
</configuration>
2.3 客户端调用服务

由于说Client端系统已经为我们生成好了和这个IHelloWorldService契约相关的 Proxy 代码了,因此我们自己手动的代码就不需要了,然后对于 Proxy 的使用我们就不需要对通过 CreateChannel 这种方式来进行调用,我们可以直接 Proxy.HelloWorldServiceClient proxy = new Proxy.HelloWorldServiceClient();,通过实例化对象的方式来实例化一个新的Proxyl对象出来就可以了,那我们实例化出来的这个 proxy 这个对象就自动包含了契约相关的信息,在 Proxy 生成以后我可以调用相应的方法来完成相应的任务,这样就实现了基于Http协议的分布式调用。在 WCF 当中无论是我们使用基于http协议的消息的传递还是使用基于 Tcp 协议的消息传递都是遵循同一个模型来开发的,如果说我们开发了一个复杂系统在原来是使用 Tcp 协议来进行数据传递的,然而在实际部署过程中要改变成Http协议,那么我们可以通过配置的方式修改一些参数就能够项目从使用Tcp协议移植到使用 Http 协议上面。

上一篇 下一篇

猜你喜欢

热点阅读