首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在Azure worker角色中托管的WCF服务中发布公共域名上的WSDL?

如何在Azure worker角色中托管的WCF服务中发布公共域名上的WSDL?
EN

Stack Overflow用户
提问于 2014-11-10 15:28:01
回答 1查看 623关注 0票数 0

我在Azure worker角色中托管了一个WCF服务。

服务可以在云服务实例(myservice.cloudapp.net)的公共域名上访问,但是,指向WSDL的链接和WSDL中的URL使用内部IP地址,这些地址不能从外部访问。因此,像Add服务引用和WCFTestClient.exe这样的工具不能像它们应该的那样顺利工作,因为它们试图访问内部IP地址。

我使用以下代码创建我的服务:

代码语言:javascript
复制
RoleInstanceEndpoint endpoint = RoleEnvironment.CurrentRoleInstance.InstanceEndpoints["MyServiceEndpoint"];
string endpointAddr = String.Format( "http://{0}/MyInteropService", endpoint.IPEndpoint );

this.serviceHost = new ServiceHost( typeof( MyInteropService ), new Uri( endpointAddr ) );

BasicHttpBinding binding = new BasicHttpBinding();

serviceHost.AddServiceEndpoint( typeof( IMyInteropService ), binding, "" );

ServiceMetadataBehavior smb = new ServiceMetadataBehavior
{
    HttpGetEnabled = true,
    HttpsGetEnabled = true,
};

serviceHost.Description.Behaviors.Add( smb );
//serviceHost.AddServiceEndpoint( ServiceMetadataBehavior.MexContractName, MetadataExchangeBindings.CreateMexHttpBinding(), "mex"); It does not matter whether I include this line or not.

serviceHost.Open();

我做错了什么?我应该如何将服务配置为在WSDL中使用公共域名?

更新:Peter的回答帮助我解决了这个问题,在我的例子中,我只需要向服务添加一个UseRequestHeadersForMetadataAddressBehavior行为,之后,就使用了公共域名(我猜现在它使用了客户端发送请求的域)。

因此,完整的工作代码如下:

代码语言:javascript
复制
RoleInstanceEndpoint endpoint = RoleEnvironment.CurrentRoleInstance.InstanceEndpoints["MyServiceEndpoint"];
string endpointAddr = String.Format( "http://{0}/MyInteropService", endpoint.IPEndpoint );

this.serviceHost = new ServiceHost( typeof( MyInteropService ), new Uri( endpointAddr ) );

BasicHttpBinding binding = new BasicHttpBinding();

serviceHost.AddServiceEndpoint( typeof( IMyInteropService ), binding, "" );

ServiceMetadataBehavior smb = new ServiceMetadataBehavior
{
    HttpGetEnabled = true,
    HttpsGetEnabled = true,
};

serviceHost.Description.Behaviors.Add( smb );

// This part solved the problem.
var requestHeaderBehavior = new UseRequestHeadersForMetadataAddressBehavior();
this.serviceHost.Description.Behaviors.Add(requestHeaderBehavior);

serviceHost.Open();
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-11-10 22:40:27

编辑:我的情况有点复杂,因为安全绑定,我相信,这可能会更容易一些。

好吧,这里有几个问题。我去看看我能不能把它们都记好。

首先,以您希望的方式公开端点,您实际上没有这样做的正确权限(即使您在提升的上下文中运行-您仍然需要这样做)。当它试图注册端点时,它将引发一个内部错误。

我必须更改拥有权限的应用程序池用户(对于工作者角色,它将是与rdp使用的凭据相同)。

代码语言:javascript
复制
var roleEndpoint = RoleEnvironment.CurrentRoleInstance.InstanceEndpoints["SslEndpoint"];
this.roleProtocol = roleEndpoint.Protocol;
this.rolePort = roleEndpoint.IPEndpoint.Port.ToString();
if (!RoleEnvironment.IsEmulated)
{
      this.roleHostname = "yourexternalhostname.com";
      var appPoolUser = "user";
      var appPoolPass = "password";
      using (var serverManager = new ServerManager())
      {
           string appPoolName = serverManager.Sites[0].Applications.First().ApplicationPoolName;
           var appPool = serverManager.ApplicationPools[appPoolName];
           appPool.ProcessModel.UserName = appPoolUser;
           appPool.ProcessModel.IdentityType = ProcessModelIdentityType.SpecificUser;
           appPool.ProcessModel.Password = appPoolPass;
           appPool.AutoStart = true;
           appPool["startMode"] = "AlwaysRunning";
           appPool.ProcessModel.IdleTimeout = TimeSpan.Zero;
           appPool.Recycling.PeriodicRestart.Time = TimeSpan.Zero;
           serverManager.CommitChanges();
       } 
}
else
{
     this.roleHostname = roleEndpoint.IPEndpoint.Address.ToString();
}

这使我能够像下面这样配置服务,您可能需要修改它以满足您的需要。密切关注被标记为重要的设置,因为我认为这些设置对于暴露您的服务是至关重要的。

代码语言:javascript
复制
var clientUrl = new Uri(string.Format("{0}://{1}:{2}/{3}", protocol, ip, port, serviceAddress + clientId));
var contractDescription = ContractDescription.GetContract(typeof(TServiceInterface));
var host = new ServiceHost(typeof(TServiceImplementation), clientUrl);

 var serviceBehaviorAttribute = new ServiceBehaviorAttribute();
 serviceBehaviorAttribute.AddressFilterMode = AddressFilterMode.Any; // Important
 serviceBehaviorAttribute.ConcurrencyMode = ConcurrencyMode.Multiple; 
 serviceBehaviorAttribute.InstanceContextMode = InstanceContextMode.PerCall;
 host.Description.Behaviors.Remove<ServiceBehaviorAttribute>();
 host.Description.Behaviors.Add(serviceBehaviorAttribute);

 var serviceMetadataBehavior = new ServiceMetadataBehavior();
 serviceMetadataBehavior.HttpGetEnabled = false;
 serviceMetadataBehavior.HttpsGetEnabled = true;
 host.Description.Behaviors.Remove<ServiceMetadataBehavior>();
 host.Description.Behaviors.Add(serviceMetadataBehavior);

 var serviceDebugBehavior = new ServiceDebugBehavior();
 serviceDebugBehavior.IncludeExceptionDetailInFaults = true;
 host.Description.Behaviors.Remove<ServiceDebugBehavior>();
 host.Description.Behaviors.Add(serviceDebugBehavior);

 var requestHeaderBehavior = new UseRequestHeadersForMetadataAddressBehavior(); // Important
 host.Description.Behaviors.Remove<UseRequestHeadersForMetadataAddressBehavior>();
 host.Description.Behaviors.Add(requestHeaderBehavior);

host.AddServiceEndpoint(new ServiceEndpoint(
            contractDescription,
            new InternalBinding(),
            new EndpointAddress(clientUrl, EndpointIdentity.CreateX509CertificateIdentity(serviceCertificate))));
host.Open();

这需要花很长的时间才能弄清楚,还有很多白发。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26847134

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档