Arhn - архитектура программирования

Как опубликовать WSDL в общедоступном домене в службе WCF, размещенной в рабочей роли Azure?

Я размещаю службу WCF в рабочей роли Azure.
Служба доступна по общедоступному доменному имени экземпляра облачных служб (myservice.cloudapp.net), однако ссылки на WSDL и URL-адреса внутри WSDL вместо этого используют внутренний IP-адрес, к которому нельзя получить доступ извне. Таким образом, такие инструменты, как Добавить ссылку на службу и 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?

ОБНОВЛЕНИЕ: ответ Питера помог мне решить проблему, в моем случае мне нужно было только добавить поведение UseRequestHeadersForMetadataAddressBehavior к службе, после чего WSDL использовал имя общедоступного домена (я думаю, теперь он использует домен, клиент отправляет запрос).

Таким образом, полный рабочий код выглядит следующим образом:

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();

  • Я потратил невероятно много времени, пытаясь решить эту проблему со старшим специалистом службы поддержки Azure. Это не простое решение, я посмотрю, смогу ли я ответить сегодня вечером, когда вернусь домой. 10.11.2014

Ответы:


1

Редактировать: моя ситуация была немного осложнена привязкой безопасности, я думаю, вам может быть немного проще

Итак, здесь есть несколько вопросов. Я посмотрю, смогу ли я запомнить их все правильно.

Во-первых, чтобы выставить конечные точки так, как вы хотите, у вас на самом деле нет правильных разрешений для этого (даже если вы работаете в контексте с повышенными правами, что вам все равно нужно будет сделать). Он выдаст внутреннюю ошибку при попытке зарегистрировать конечную точку.

Мне пришлось изменить пользователя пула приложений, у которого были права на это (это будут те же учетные данные, которые вы используете для 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();

Некоторые биты опущены и т. д. Это заняло очень много времени, чтобы понять, и много седых волос.

10.11.2014
  • Большое спасибо за подробный ответ. Мне достаточно было добавить UseRequestHeadersForMetadataAddressBehavior в сервис, и теперь он работает, остальные части кода добавлять не пришлось. 11.11.2014
  • Не беспокойся. Я думаю, что дополнительные проблемы возникают, когда вам нужно защитить хост с помощью сертификата (перенаправление с балансировщика нагрузки на внутренний IP-адрес все портит), просто кое-что нужно иметь в виду, если вы его измените. 11.11.2014
  • Новые материалы

    Коллекции публикаций по глубокому обучению
    Последние пару месяцев я создавал коллекции последних академических публикаций по различным подполям глубокого обучения в моем блоге https://amundtveit.com - эта публикация дает обзор 25..

    Представляем: Pepita
    Фреймворк JavaScript с открытым исходным кодом Я знаю, что недостатка в фреймворках JavaScript нет. Но я просто не мог остановиться. Я хотел написать что-то сам, со своими собственными..

    Советы по коду Laravel #2
    1-) Найти // You can specify the columns you need // in when you use the find method on a model User::find(‘id’, [‘email’,’name’]); // You can increment or decrement // a field in..

    Работа с временными рядами спутниковых изображений, часть 3 (аналитика данных)
    Анализ временных рядов спутниковых изображений для данных наблюдений за большой Землей (arXiv) Автор: Рольф Симоэс , Жильберто Камара , Жильберто Кейрос , Фелипе Соуза , Педро Р. Андраде ,..

    3 способа решить квадратное уравнение (3-й мой любимый) -
    1. Методом факторизации — 2. Используя квадратичную формулу — 3. Заполнив квадрат — Давайте поймем это, решив это простое уравнение: Мы пытаемся сделать LHS,..

    Создание VR-миров с A-Frame
    Виртуальная реальность (и дополненная реальность) стали главными модными терминами в образовательных технологиях. С недорогими VR-гарнитурами, такими как Google Cardboard , и использованием..

    Демистификация рекурсии
    КОДЕКС Демистификация рекурсии Упрощенная концепция ошеломляющей О чем весь этот шум? Рекурсия, кажется, единственная тема, от которой у каждого начинающего студента-информатика..