代码之家  ›  专栏  ›  技术社区  ›  WayneC

隐藏WCF中MEX/WSDL的REST端点

  •  6
  • WayneC  · 技术社区  · 15 年前

    我有一个WCF服务,每个服务都有REST和SOAP端点。这与本帖的实施类似: REST / SOAP endpoints for a WCF service 配置如下:

    <services>
      <service name="TestService">
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
        <endpoint address="soap" binding="basicHttpBinding" contract="ITestService"/>
        <endpoint address="rest" binding="webHttpBinding" contract="ITestService"/>
      </service>
    </services>
    

    问题是,REST端点在生成的WSDL中显示为一个附加的端口和绑定。

    是否有任何方法可以防止REST端点包含在WSDL中?

    3 回复  |  直到 13 年前
        1
  •  1
  •   jrista    15 年前

    您可以获取WSDL的副本,手动编辑它以删除不需要的工件,并将其存储在已知位置。一旦您拥有了删除不需要的工件的WSDL版本,您就可以重定向?到该位置的WSDL查询:

    <behaviors>
     <serviceBehaviors>
        <behavior name="TestServiceBehavior">
         <serviceMetadata httpGetEnabled="True" externalMetadataLocation="http://localhost/TestService.wsdl"/>
        </behavior>
     </serviceBehaviors>
    </behaviors>
    

    一些人对这个解决方案提出了警告。你必须小心编辑什么。如果更改了合同的关键方面,WCF可能无法处理从中生成的客户端的消息。删除端点通常不是什么大问题,但是更改绑定、操作、消息类型等的名称可能会导致问题。

    你还需要了解进口。WCF生成的WSDL通常定义端点,然后导入另一个定义实际服务契约的.wsdl。tern中的服务契约WSDL通常导入定义消息和数据类型的几个.xsd文件。您需要确保相对于根.wsdl上载了这些元素的副本,并更新导入元素以适当地引用它们。

    另一个问题是,您现在正在手动控制您的合同……这意味着如果您更改了它,您必须再次编辑它,并在托管.wsdl文件的任何站点上替换它。现在,正确设计的契约不应该改变,因为这打破了关于Web服务的基本SOA规则之一。但是,您似乎是在进行代码优先开发,因此需要注意这一点。

        2
  •  1
  •   infocyde    14 年前

    如果有一个属性来修饰端点,使其在未来的WCF版本中对mex/wsdl生成隐藏起来,那就更好了,因为正是这个原因(从SOAP客户机隐藏RESTful服务)。

        3
  •  1
  •   WayneC    13 年前

    找到一个 得体的 使用 IWsdlExportExtension . 可能有一种更健壮/更可重用的方法来实现这一点,但此解决方案要求将所有REST端点的约定命名为“REST”。以下是连接到所有REST端点的端点行为的相关部分:

    public void ExportEndpoint(WsdlExporter exporter, WsdlEndpointConversionContext context)
    {
        // Remove all REST references (binding & port) from SOAP WSDL
        foreach (ServiceDescription wsdl in exporter.GeneratedWsdlDocuments)
        {
            // Remove REST bindings
            foreach (Binding binding in wsdl.Bindings)
            {
                if (binding.Name == "REST")
                {
                    wsdl.Bindings.Remove(binding);
                    break;
                }
            }
    
            // Remove REST ports
            foreach (Service service in wsdl.Services)
            {
                foreach (Port port in service.Ports)
                {
                    if (port.Name == "REST")
                    {
                        service.Ports.Remove(port);
                        break;
                    }
                }
            }
        }  
    }