整理一下思路,探讨WCF(二)

基于上文的Demo,我们观察到,在IIS宿主中,配置文件有以下特征:

<system.serviceModel>
  <services>
    <service name="WcfService9.Service1" behaviorConfiguration="WcfService9.Service1Behavior">
      <endpoint address="" binding="wsHttpBinding" contract="WcfService9.IService1">
        <identity>
          <dns value="localhost"/>
        </identity>
      </endpoint>
      <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
    </service>
  </services>
  <behaviors>
    <serviceBehaviors>
      <behavior name="WcfService9.Service1Behavior">
        <serviceMetadata httpGetEnabled="true"/>
        <serviceDebug includeExceptionDetailInFaults="false"/>
      </behavior>
    </serviceBehaviors>
  </behaviors>
</system.serviceModel>

下面修改这个配置文件,看怎么搞死WCF:

1.删除MEX终结点:

<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>

一切照常,Service可以运行,Client也可以调用Service的方法。

image

image

2.不删除MEX终结点,只删除行为中的serviceMetadata 标签:

<serviceMetadata httpGetEnabled="true"/>

会发现Service不能运行,更不要说Client能调用Service了。

image

具体异常信息如下所示:

The contract name 'IMetadataExchange' could not be found in the list of contracts implemented by the service Service1.  Add a ServiceMetadataBehavior to the configuration file or to the ServiceHost directly to enable support for this contract.

3.怎么办?干脆连MEX那一行也删了,新的配置文件如下所示:

    <system.serviceModel>
        <services>
            <service name="WcfService9.Service1" behaviorConfiguration="WcfService9.Service1Behavior">
                <!-- Service Endpoints -->
                <endpoint address="" binding="wsHttpBinding" contract="WcfService9.IService1">
                    <identity>
                        <dns value="localhost"/>
                    </identity>
                </endpoint>
            </service>
        </services>
        <behaviors>
            <serviceBehaviors>
                <behavior name="WcfService9.Service1Behavior">
                    <serviceDebug includeExceptionDetailInFaults="false"/>
                </behavior>
            </serviceBehaviors>
        </behaviors>
    </system.serviceModel>

于是,Service又能运行了,

image

但是,因为没有公布MEX元数据交换中间点,所以,我们不能在Client端添加对Service的引用:

image

4.好吧,看来我们要想在httpGetEnabled上做文章,只能保留MEX终结点。既然删除<serviceMetadata httpGetEnabled="true"/> 这个标签会导致Service不能运行,我们在删除httpGetEnabled属性的同时,保留这个标签,如下所示:

  <system.serviceModel>
    <services>
      <service name="WcfService9.Service1" behaviorConfiguration="WcfService9.Service1Behavior">
        <endpoint address="" binding="wsHttpBinding" contract="WcfService9.IService1">
          <identity>
            <dns value="localhost"/>
          </identity>
        </endpoint>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="WcfService9.Service1Behavior">
          <serviceMetadata/>
          <serviceDebug includeExceptionDetailInFaults="false"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>

我们发现,Service又能运行了,但是http://localhost:40159/Service1.svc页面与前面成功运行起来的页面不太一样:

image

尽管如此,我们还是能够正常使用这个Service:

image

5.哦,原来是这样。看来<serviceMetadata httpGetEnabled="true"/>是不能赶尽杀绝的,至少要保留一个<serviceMetadata/>标签。

我们将配置文件修改为:

<serviceMetadata httpGetEnabled="false"/>

,再次运行Service,会发现和<serviceMetadata/>具有相同的效果。可见,httpGetEnabled默认值为false。

6.我们在第4次测试中,发现<serviceMetadata httpGetEnabled="true"/><serviceMetadata httpGetEnabled="false"/>所产生的Service页面不同:

image

image

但是,Client都是可以调用Service的。那么差异到底在哪里呢?

经测试,在MEX终结点存在的情况下,是否设置httpGetEnabled是没有区别的。

但是,如果删除MEX终结点,差异就出来了:

对于<serviceMetadata httpGetEnabled="true"/>,我们发现,Service可以运行,Client也可以调用Service。

而对于<serviceMetadata httpGetEnabled="false"/>,这就是测试3的情形了,Service虽然可以运行,但是因为没有公布元数据终结点,所以Client不能调用Service。

好了,可以结案陈词了。

MEX和httpGetEnabled是公布元数据终结点的两种不同方式。

MEX可以适用于任何binding,比如说TCP、HTTP。

httpGetEnabled则仅适用于HTTP。

那好,既然我们现在就处于IIS宿主的环境下,那么二者就都可以使用。

1)只设置MEX是不够的,在此基础上,我们还要设置httpGetEnabled="true"

2)只设置<serviceMetadata httpGetEnabled="true"/>就够了。

此外,最恶心的莫过于,如果不设置<serviceMetadata httpGetEnabled="true"/>,但是仍然要保留<serviceMetadata>标签。我猜,这也许源于自定义behavior的设计原理。在配置文件中必须要声明这个标签,哪怕是一个空标签,也要保留,从而在WCF运行起来的时候,会找到这个serviceMetadata标签,进行实例化(设置httpGetEnabled默认值为false)。

此时,我已经能想象到WCF设计团队脸上的无奈了。

原文地址:https://www.cnblogs.com/Jax/p/1597885.html