3

我正在开发一个 WCF 应用程序,该应用程序将在此过程中部署到各种服务器,并且我希望不必记住每次进行部署时都更改 app.config。起初,我的 app.config serviceModel 部分如下所示:

<system.serviceModel>  
<serviceHostingEnvironment aspNetCompatibilityEnabled="false" />  
<behaviors>  
    <serviceBehaviors>  
        <behavior name="MyDefaultServiceBehavior">   
            <serviceMetadata httpGetEnabled="true" httpGetUrl="http://localhost:8888/MyService" />  
            <serviceDebug includeExceptionDetailInFaults="true" />  
        </behavior>  
    </serviceBehaviors>  
</behaviors>  
<services>  
    <service behaviorConfiguration="MyDefaultServiceBehavior" name="MyService">   
        <endpoint address="net.tcp://localhost:9001/MyService" binding="netTcpBinding" contract="IMyService" name="NetTcpBinding_IMyService" />  
    </service>  
</services>  

当我访问本地机器上运行的服务时,这在开发中运行良好。当我部署它时,WSDL 包含仍然指向 localhost 的绝对路径:

<xsd:import schemaLocation=http://localhost:8888/MyService?xsd=xsd0 namespace="http://tempuri.org/" />

因此,我可以像这样更改 app.config 中的 httpGetUrl:

<serviceMetadata httpGetEnabled="true" httpGetUrl=http://devserver1:8888/MyService />

现在 wsdl 可以在该服务器上正常工作。问题是我必须在每个部署的 app.config 中手动设置地址。

有没有办法:
1. wsdl 是否已经包含所有内容以便没有导入?
或者
2. 在 wsdl 导入语句中使用相对路径?

或任何其他建议将不胜感激。如果不是因为这个 wsdl 问题,我有两个开发服务器可以自动部署。

由于这只是为了生成代理,我想我可以自己生成代理并分发它,但我宁愿让用户自己生成代理。

谢谢!丹尼尔

4

3 回答 3

3

您可以以编程方式设置httpGetUrl的值,并将其设置为包含托管服务的服务器的机器名称的绝对地址。然后,生成的 WSDL 中的导入语句也将使用服务器的机器名称。

如果正在为您创建 WCF 主机(例如,您在 IIS 下托管),那么您将需要创建自定义ServiceHostFactory以访问ServiceHost。例如:

using System;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.ServiceModel.Description;

namespace WebApplication
{
  public class TestServiceHostFactory : ServiceHostFactory
  {
     protected override ServiceHost CreateServiceHost(Type serviceType, 
                                                      Uri[] baseAddresses)
      {
        ServiceHost host = base.CreateServiceHost(serviceType, 
                                                  baseAddresses);
        ServiceMetadataBehavior metadataBehavior = 
                                new ServiceMetadataBehavior();
        metadataBehavior.HttpGetEnabled = true;
        metadataBehavior.HttpGetUrl = new Uri(string.Format(
                              "http://{0}/WebApplication/TestService.svc", 
                              Environment.MachineName));
        host.Description.Behaviors.Add(metadataBehavior);
        return host;
      }
  }
}

然后在服务的 .svc 文件中指定这个工厂:

<%@ ServiceHost Language="C#" 
                Service="WebApplication.TestService" 
                CodeBehind="TestService.svc.cs" 
                Factory="WebApplication.TestServiceHostFactory" %>

如果您自己创建 WCF 主机,那么您的代码将如下所示:

ServiceHost host = new ServiceHost(typeof(WebApplication.TestService));
ServiceMetadataBehavior metadataBehavior = new ServiceMetadataBehavior();
metadataBehavior.HttpGetEnabled = true;
metadataBehavior.HttpGetUrl = new Uri(string.Format(
                              "http://{0}/WebApplication/TestService.svc", 
                              Environment.MachineName));
host.Description.Behaviors.Add(metadataBehavior);
于 2009-02-26T22:08:55.833 回答
2

Daniel Richardson 上面留下的答案是一个很好的答案,我认为对于大多数人来说,这将是首选的解决方案。然而,由于我们的网络布局和需要访问我们服务器的少数人,我正在做一些不同的事情。

我已将 app.config 更改为包含“myServiceServer”的 httpGetUrl:

<serviceMetadata httpGetEnabled="true" httpGetUrl=http://myServiceServer:8888/MyService />

要使用我的服务,必须先添加一个主机文件条目,将“myServiceServer”映射到正确的 IP 地址。这对我们的问题很有效,因为无法从任何常见的机器名称或 IP 地址解析 IP 地址。这是因为分离的网络仅通过具有某种 NAT 的 VPN 连接。

于 2009-03-03T18:39:18.730 回答
0

WCF 中显然有一个非常隐藏的选项,它支持使用与传入请求相同的主机名,这通常是正确的。(我认为它不是默认设置的唯一原因是为了向后兼容,尽管如果他们将其设为默认设置可能会更好。)

在我找到这颗特殊的宝石之前,我花了很多时间寻找和拉扯头发(虽然现在我知道了这个神奇的词,但我找到了另一个来自与我的类似旅程的答案)。

要启用它,请在添加的相同位置添加以下代码ServiceMetadataBehavior

host.Description.Behaviors.Remove<UseRequestHeadersForMetadataAddressBehavior>();
host.Description.Behaviors.Add(new UseRequestHeadersForMetadataAddressBehavior());
于 2020-11-13T06:09:42.200 回答