Asp.net Самостоятельная служба WCF WSDL с относительными путями
Я работаю над приложением WCF, которое будет разворачиваться на различных серверах по пути, и мне бы хотелось, чтобы мне не приходилось помнить об изменении app.config каждый раз, когда я выполняю развертывание. Сначала мой раздел serviceModel app.config выглядел так:
<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/" />
Итак, я могу изменить httpGetUrl в app.config следующим образом:
<serviceMetadata httpGetEnabled="true" httpGetUrl=http://devserver1:8888/MyService />
И теперь wsdl корректно работает на этом сервере. Проблема в том, что мне приходится вручную устанавливать адрес в каждом развернутом app.config.
Есть ли способ:
1. Включить уже все в wsdl, чтобы не было импорта?
или
2. Использовать относительные пути в операторах импорта wsdl?
Или любые другие предложения будут оценены. У меня есть два сервера разработки, на которых развертывание автоматизировано, если бы не проблема с wsdl.
Поскольку это только для генерации прокси, я полагаю, я мог бы сгенерировать прокси и распространить его сам, но я бы предпочел позволить пользователям генерировать прокси самостоятельно.
Спасибо! Даниэль
Ответов (3)3
Ответ, оставленный выше Дэниэлом Ричардсоном, является хорошим, и я думаю, что для большинства людей это было бы предпочтительным решением. Однако из-за нашей схемы сети и небольшого числа людей, которым потребуется доступ к нашему серверу, я делаю немного другое.
Я изменил свой app.config на httpGetUrl, содержащий myServiceServer:
<serviceMetadata httpGetEnabled="true" httpGetUrl=http://myServiceServer:8888/MyService />
Чтобы использовать мою службу, кто-то должен сначала добавить в файл хоста запись, которая сопоставляет myServiceServer с правильным IP-адресом. Это хорошо работает для нашей проблемы, потому что IP-адрес не может быть определен с помощью любого общего имени машины или IP-адреса. Это происходит из-за разделенных сетей, которые связаны только через VPN с каким-то NAT.
По-видимому, в WCF есть очень хорошо скрытая опция, которая поддерживает использование того же имени хоста, что и входящий запрос, что обычно бывает правильным. (Я предполагаю, что единственная причина, по которой это не значение по умолчанию, - это обратная совместимость, хотя, вероятно, было бы лучше, если бы они все равно сделали его по умолчанию.)
Потребовалось много поисков и выдергивания волос, прежде чем я нашел этот драгоценный камень (хотя теперь, когда я знаю волшебное слово, я нашел другой ответ который пришел из того же путешествия, что и мой).
Чтобы включить его, добавьте следующий код в то же место, где вы добавляете ServiceMetadataBehavior
:
host.Description.Behaviors.Remove<UseRequestHeadersForMetadataAddressBehavior>();
host.Description.Behaviors.Add(new UseRequestHeadersForMetadataAddressBehavior());
Вы можете установить значение 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);