【问题标题】:WCF and Multiple Host HeadersWCF 和多个主机标头
【发布时间】:2010-09-30 03:50:53
【问题描述】:

我的雇主网站有多个主机名,它们都访问同一个服务器,我们只是出于品牌推广目的显示不同的皮肤。

不幸的是,WCF 在这种情况下似乎无法正常工作。

我试过overriding the default host with a custom host factory

这不是一个可接受的解决方案,因为它需要在所有主机上工作,而不仅仅是 1 个。

我也查看了this blog post,但要么我无法让它工作,要么它不能解决我的问题。

我得到的错误是“这个集合已经包含一个带有 http 方案的地址”

一定有办法配置这个,请帮忙:)

【问题讨论】:

  • 您是使用 IIS 托管 WCF 还是构建自定义托管服务提供商?
  • 另外,您遇到的具体问题/问题是什么? IE。服务是否无法运行、返回不正确的响应 (URL) 还是服务不知道哪个客户端正在调用?
  • 这个集合已经包含一个带有 http 方案的地址

标签: c# wcf iis iis-6


【解决方案1】:

不涉及任何代码或配置更改的简单解决方法是在 IIS 中创建另一个网站,该网站指向相同的物理目录和相同的应用程序池,但具有不同的主机头绑定。可以为尽可能多的不同主机名执行此操作。

【讨论】:

    【解决方案2】:

    我几天前遇到了这个问题。实际上,我的情况与 Ryu 在他的问题中最初描述的情况相同。我们为许多客户提供一个虚拟目录,但每个客户都有自己的绑定。比如“http://company1.product.com”、“http://company2.product.com”等

    here 描述的解决方案有效。但是价格是多少!每次需要添加新绑定时,我们都应该更改 web.config。而且 web.config 应该包含绝对路径前缀 喜欢<add prefix=”http://company1.product.com”/>

    可以绕过第一个问题。我为 WCF 服务编写了自己的 CustomHostFactory,我在其中动态添加端点。我从 IIS 绑定中检索到这个端点(有一种从 IIS 获取信息的方法)。

    这里是示例代码:

    protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
    {
        var serviceHost = base.CreateServiceHost(serviceType, baseAddresses);
        var webHttpBinding = new WebHttpBinding();
        var serviceEndpoint1 = serviceHost.AddServiceEndpoint(typeof(IService), webHttpBinding,
                                                             "http://company2.product.com/WCFService/Service.svc");
    
        var serviceEndpoint2 = serviceHost.AddServiceEndpoint(typeof(IService), webHttpBinding,
                                                     "http://company1.product.com/WCFService/Service.svc");
    
        var webHttpBehavior = new WebHttpBehavior();
    
        serviceEndpoint1.Behaviors.Add(webHttpBehavior);
        serviceEndpoint2.Behaviors.Add(webHttpBehavior);
    
        return serviceHost;
    }
    

    您可以从 IIS 中检索它们,而不是硬编码端点 url。 但是 ServiceHost 在应用程序启动时创建一次。所以如果你需要添加新的绑定,你应该重启 IIS。这不是我们的解决方案。

    这就是我们决定迁移到 asmx 的原因(如 here 所述)。 等到 Framework 4.0 发布,应该支持多个绑定。

    【讨论】:

    • 使用 .NET 4.0,您不再需要在配置中指定所有主机头,只需添加 <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />,如 Rampo 的博客中所述。感谢您的链接。
    【解决方案3】:

    我认为上面发布的 主机基地址 解决方案不适用于 IIS 托管的网站(OP 确实提到这是针对他雇主的网站) .

    this blog post

    此外,thaBadDawg 进一步提出的另一个答案在指定多个主机头的情况下不起作用 - 你只会得到 OP 提到的错误(“这个集合已经包含一个地址方案http”。)

    我认为到目前为止提到的任何解决方案都不会起作用,因为 WCF 似乎不允许单个站点访问单个服务,该站点具有来自所有站点的多个主机标头。对于 .Net 3.5(及更低版本),我能找到的唯一解决方法是为每个主机标头创建不同的合同,并使用自定义 ServiceHostFactory 根据指定的合同使用正确的主机标头。这根本不实用。显然是.Net 4.0 will resolve this issue

    【讨论】:

    • 另一种解决方法是 struhtanov 提到的解决方法。基本上您需要做的就是为每个主机创建不同的端点(不必更改合同)。
    【解决方案4】:

    我相信你现在已经想通了,但无论如何我还是会在这里发帖。

    我遇到了这个确切的问题,并且一直在试图解决这个问题。最好的解决方案是将主机基地址放在您的服务定义中,这样服务就可以在这些多个地址下运行。要使此解决方案起作用,您仍然需要覆盖 ServiceHostFactory。既然你已经这样做了,就把它留在那儿。

    <service behaviorConfiguration="ServiceBehaviour" name="Api.Service">
        <endpoint address="soap" binding="basicHttpBinding" contract="Api.IService" />
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
        <host>
          <baseAddresses>
            <add baseAddress="http://host1.com/Api" />
            <add baseAddress="http://host2.com/Api" />
          </baseAddresses>
        </host>
      </service>
    

    【讨论】:

    【解决方案5】:

    如果您没有在端点中放置地址,那么它应该解析为任何服务器访问该服务。我使用此代码,它从 IIS 解析为我的 .local 地址和我的 .com 地址。

    <system.serviceModel>
        <services>
            <service name="ServiceName" behaviorConfiguration="ServiceName.Service1Behavior">
                <endpoint address="" binding="wsHttpBinding" contract="iServiceName">
                </endpoint>
                <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
            </service>
        </services>
        <behaviors>
            <serviceBehaviors>
                <behavior name="ServiceName.Service1Behavior">
                    <!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
                    <serviceMetadata httpGetEnabled="true"/>
                    <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
                    <serviceDebug includeExceptionDetailInFaults="true"/>
                </behavior>
            </serviceBehaviors>
        </behaviors>
    </system.serviceModel>
    

    【讨论】:

    • 当您有多个主机标头时,此方案是否有效?看起来它对我不起作用(ASP.NET 3.5 / IIS 6)。 zcrar70 的帖子似乎同意。
    猜你喜欢
    • 1970-01-01
    • 2012-05-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-15
    • 2011-10-04
    相关资源
    最近更新 更多