我在Azure worker角色中托管了一个WCF服务。
服务可以在云服务实例(myservice.cloudapp.net)的公共域名上访问,但是,指向WSDL的链接和WSDL中的URL使用内部IP地址,这些地址不能从外部访问。因此,像Add服务引用和WCFTestClient.exe这样的工具不能像它们应该的那样顺利工作,因为它们试图访问内部IP地址。
我使用以下代码创建我的服务:
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行为,之后,就使用了公共域名(我猜现在它使用了客户端发送请求的域)。
因此,完整的工作代码如下:
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();发布于 2014-11-10 22:40:27
编辑:我的情况有点复杂,因为安全绑定,我相信,这可能会更容易一些。
好吧,这里有几个问题。我去看看我能不能把它们都记好。
首先,以您希望的方式公开端点,您实际上没有这样做的正确权限(即使您在提升的上下文中运行-您仍然需要这样做)。当它试图注册端点时,它将引发一个内部错误。
我必须更改拥有权限的应用程序池用户(对于工作者角色,它将是与rdp使用的凭据相同)。
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();
}这使我能够像下面这样配置服务,您可能需要修改它以满足您的需要。密切关注被标记为重要的设置,因为我认为这些设置对于暴露您的服务是至关重要的。
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();这需要花很长的时间才能弄清楚,还有很多白发。
https://stackoverflow.com/questions/26847134
复制相似问题