WCF и заголовки нескольких хостов - PullRequest
10 голосов
/ 08 января 2009

На моем веб-сайте работодателей есть несколько имен хостов, которые попадают на один и тот же сервер, и мы просто показываем разные скины для целей брендинга.

К сожалению, WCF не очень хорошо работает в этой ситуации.

Я пытался переопределить хост по умолчанию с пользовательской фабрикой хостов .

Это неприемлемое решение, потому что оно должно работать со всех хостов, а не только с 1.

Я также просмотрел это сообщение в блоге , но либо я не смог заставить его работать, либо он не предназначен для решения моей проблемы.

Я получаю сообщение об ошибке: «Эта коллекция уже содержит адрес со схемой http»

Должен быть способ настроить это, пожалуйста, помогите:)

Ответы [ 5 ]

5 голосов
/ 11 ноября 2009

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

См. это сообщение в блоге

Кроме того, другой ответ на thaBadDawg не будет работать, если указано несколько заголовков хоста - вы просто получите ошибки, о которых упоминает OP («Эта коллекция уже содержит адрес со схемой» HTTP».)

Я не думаю, что какое-либо из упомянутых решений будет работать, потому что не похоже, что WCF позволяет одному сервису быть доступным для одного сайта с несколькими заголовками узлов со всех сайтов. Единственный обходной путь, который я мог найти для .Net 3.5 (и ниже), - это создать разные контракты для каждого из заголовков хоста и использовать настраиваемый ServiceHostFactory для использования правильного заголовка хоста, в зависимости от которого указан контракт. Это совсем не практично. Видимо .Net 4.0 решит эту проблему .

5 голосов
/ 08 января 2009

Если вы не указали адрес в конечной точке, он должен разрешиться на любой сервер, подключенный к службе. Я использую этот код, и он разрешает и мой адрес .local, и мой адрес .com из IIS.

<system.serviceModel>
    <services>
        <service name="ServiceName" behaviorConfiguration="ServiceName.Service1Behavior">
            <endpoint address="" binding="wsHttpBinding" contract="iServiceName">
            </endpoint>
            <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
        </service>
    </services>
    <behaviors>
        <serviceBehaviors>
            <behavior name="ServiceName.Service1Behavior">
                <!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
                <serviceMetadata httpGetEnabled="true"/>
                <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
                <serviceDebug includeExceptionDetailInFaults="true"/>
            </behavior>
        </serviceBehaviors>
    </behaviors>
</system.serviceModel>
3 голосов
/ 04 февраля 2010

Я столкнулся с этой проблемой несколько дней назад. На самом деле у меня та же ситуация, которую Рю описал в своем вопросе. У нас есть один виртуальный каталог для многих клиентов, но у каждого из них есть своя привязка. Как "http://company1.product.com"," http://company2.product.com" и т. Д.

Описанное решение здесь работает. Но какова цена! Мы должны менять web.config каждый раз, когда нам нужно добавить новую привязку. А также web.config должен содержать префикс абсолютного пути как <add prefix=”http://company1.product.com”/>.

Возможно обойти первую проблему. Я написал свой собственный CustomHostFactory для службы WCF, где я динамически добавляю конечные точки. И эти конечные точки я извлекаю из привязок IIS (есть способ получить информацию из IIS).

Вот пример кода:

protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
    var serviceHost = base.CreateServiceHost(serviceType, baseAddresses);
    var webHttpBinding = new WebHttpBinding();
    var serviceEndpoint1 = serviceHost.AddServiceEndpoint(typeof(IService), webHttpBinding,
                                                         "http://company2.product.com/WCFService/Service.svc");

    var serviceEndpoint2 = serviceHost.AddServiceEndpoint(typeof(IService), webHttpBinding,
                                                 "http://company1.product.com/WCFService/Service.svc");

    var webHttpBehavior = new WebHttpBehavior();

    serviceEndpoint1.Behaviors.Add(webHttpBehavior);
    serviceEndpoint2.Behaviors.Add(webHttpBehavior);

    return serviceHost;
}

И вместо жесткого кодирования URL-адресов конечных точек их можно получить из IIS. Но ServiceHost создается один раз при запуске приложения. Поэтому, если вам нужно добавить новую привязку, вам нужно перезапустить IIS. Это не решение для нас.

Именно поэтому мы решили перейти на asmx (как описано здесь ). И дождитесь выпуска Framework 4.0, где должны поддерживаться несколько привязок.

0 голосов
/ 28 мая 2015

Простой обходной путь, который не требует каких-либо изменений кода или конфигурации, состоит в создании еще одного веб-сайта в IIS, который указывает на тот же физический каталог и тот же пул приложений, но с другой привязкой заголовка узла. Это можно сделать для любого количества имен хостов.

0 голосов
/ 25 марта 2009

Я уверен, что вы уже поняли это, но просто для удовольствия, я все равно выложу здесь.

У меня была именно эта проблема, и я потратил целую вечность, пытаясь ее решить. Лучшее решение - указать базовые адреса хоста в определении службы, что позволяет службе работать с этими несколькими адресами. Чтобы это решение работало, вам все еще нужно переопределить ServiceHostFactory. Так как вы уже сделали это, просто оставьте это там.

<service behaviorConfiguration="ServiceBehaviour" name="Api.Service">
    <endpoint address="soap" binding="basicHttpBinding" contract="Api.IService" />
    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
    <host>
      <baseAddresses>
        <add baseAddress="http://host1.com/Api" />
        <add baseAddress="http://host2.com/Api" />
      </baseAddresses>
    </host>
  </service>
...