具有相对路径的 Asp.net 自托管 WCF 服务 WSDL
Posted
技术标签:
【中文标题】具有相对路径的 Asp.net 自托管 WCF 服务 WSDL【英文标题】:Asp.net Self Hosted WCF Service WSDL with relative paths 【发布时间】:2010-10-09 21:53:34 【问题描述】:我正在开发一个 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 问题,我有两个自动部署的开发服务器。
由于这只是为了生成代理,我想我可以自己生成代理并分发它,但我宁愿让用户自己生成代理。
谢谢! 丹尼尔
【问题讨论】:
【参考方案1】:您可以通过编程方式设置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);
【讨论】:
我就是这么干的。 对我来说更大的问题是不是每个人都可以使用机器名访问服务器。对于某些人来说,它甚至无法解决。您的解决方案很好地回答了我的问题,但不幸的是,我将问题简化了太多,并没有解决我的问题。请参阅其他评论以获取解决方案。【参考方案2】:丹尼尔理查森上面留下的答案是一个很好的答案,我认为对于大多数人来说,这将是首选的解决方案。但是,由于我们的网络布局和需要访问我们服务器的少数人,我正在做一些不同的事情。
我已将 app.config 更改为包含“myServiceServer”的 httpGetUrl:
<serviceMetadata httpGetEnabled="true" httpGetUrl=http://myServiceServer:8888/MyService />
要使用我的服务,必须先添加一个主机文件条目,将“myServiceServer”映射到正确的 IP 地址。这对我们的问题很有效,因为无法从任何常见的机器名称或 IP 地址解析 IP 地址。这是因为分离的网络仅通过 *** 连接,并且进行了某种 NAT。
【讨论】:
【参考方案3】:WCF 中显然有一个非常隐蔽的选项,它支持使用与传入请求相同的主机名,这通常是正确的。 (我认为它不是默认设置的唯一原因是为了向后兼容,尽管如果他们将其设为默认设置可能会更好。)
在我找到这颗特别的宝石之前,我花了很多时间寻找和拉扯头发(虽然现在我知道了这个神奇的词,但我找到了来自与我类似的旅程的 another answer)。
要启用它,请在添加 ServiceMetadataBehavior
的相同位置添加以下代码:
host.Description.Behaviors.Remove<UseRequestHeadersForMetadataAddressBehavior>();
host.Description.Behaviors.Add(new UseRequestHeadersForMetadataAddressBehavior());
【讨论】:
以上是关于具有相对路径的 Asp.net 自托管 WCF 服务 WSDL的主要内容,如果未能解决你的问题,请参考以下文章
强大的自托管服务器的最佳选择:WCF 与 ASP.NET Web Api
如何在托管的 ASP.NET Web API 中使用 System.IO.File 提供相对路径?