WCF динамически устанавливает конечную точку и привязку в коде - PullRequest
5 голосов
/ 27 августа 2011

Да, я читал другие вопросы на SO, MSDN и других сайтах, но я не нашел ответов настолько ясных, насколько я могу понять. Мне нужно установить ссылки WCF моего приложения Silverlight относительно сайта, с которого оно загружено, но я не могу заставить его работать. С самим сервисом проблем нет, он работает. Когда я перехожу с локального на свой реальный сервер, в моем приложении SL появляются ошибки с жалобой на отсутствие соединения с localhost.

Вот мой ServiceReferences.ClientConfig файл:

    <configuration>
        <system.serviceModel>
            <bindings>
                <customBinding>
                    <binding name="CustomBinding_AccountManager">
                        <binaryMessageEncoding />
                        <httpTransport maxReceivedMessageSize="2147483647" maxBufferSize="2147483647" />
                    </binding>
                    <binding name="CustomBinding_FileManager">
                        <binaryMessageEncoding />
                        <httpTransport maxReceivedMessageSize="2147483647" maxBufferSize="2147483647" />
                    </binding>
                    <binding name="CustomBinding_SiteManager">
                        <binaryMessageEncoding />
                        <httpTransport maxReceivedMessageSize="2147483647" maxBufferSize="2147483647" />
                    </binding>
                </customBinding>
            </bindings>
            <client>
                <endpoint address="http://localhost:60322/AccountManager.svc"
                    binding="customBinding" bindingConfiguration="CustomBinding_AccountManager"
                    contract="AccountManager.AccountManager" name="CustomBinding_AccountManager" />
                <endpoint address="http://localhost:60322/FileManager.svc" binding="customBinding"
                    bindingConfiguration="CustomBinding_FileManager" contract="FileManager.FileManager"
                    name="CustomBinding_FileManager" />
                <endpoint address="http://localhost:60322/SiteManager.svc" binding="customBinding"
                    bindingConfiguration="CustomBinding_SiteManager" contract="SiteManager.SiteManager"
                    name="CustomBinding_SiteManager" />
            </client>
        </system.serviceModel>
    </configuration>

Да, я буду оптимизировать размеры буфера / сообщения, и я знаю возможные эксплойты DoS, пока забудем об этом, они мне нужны для передачи больших файлов. Подход, который я попробовал, заключается в том, что при создании экземпляров клиентов я использовал этот код:

    fileManager = new FileManagerClient(new BasicHttpBinding(), new EndpointAddress("http://" + Settings.Host + "/FileManager.svc"));
    accManager = new AccountManagerClient(new BasicHttpBinding(), new EndpointAddress("http://" + Settings.Host + "/AccountManager.svc"));

где Settings.Host - это мой собственный метод, который возвращает мне хост, с которого работает, тестируется и работает приложение SL. Когда я загрузил свой XAP и попытался, он все еще хотел перейти на http://localhost:60322/AccountManager.svc, после дальнейшего изучения я понял, что в невидимых файлах все еще есть много ссылок на localhost:

AccountManager.disco

<?xml version="1.0" encoding="utf-8"?>
<discovery xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/disco/">
  <contractRef ref="http://localhost:60322/AccountManager.svc?wsdl" docRef="http://localhost:60322/AccountManager.svc" xmlns="http://schemas.xmlsoap.org/disco/scl/" />
</discovery>

Части AccountManager.wsdl: ... <wsdl:import namespace="" location="http://localhost:60322/AccountManager.svc?wsdl=wsdl0" />... ... [много объявлений операций] ...

<wsdl:service name="AccountManager">
    <wsdl:port name="CustomBinding_AccountManager" binding="tns:CustomBinding_AccountManager">
      <soap12:address location="http://localhost:60322/AccountManager.svc" />
      <wsa10:EndpointReference>
        <wsa10:Address>http://localhost:60322/AccountManager.svc</wsa10:Address>
      </wsa10:EndpointReference>
    </wsdl:port>
  </wsdl:service>

Часть AccountManager1.xsd:

<xs:import schemaLocation="http://localhost:60322/AccountManager.svc?xsd=xsd2" namespace="http://schemas.datacontract.org/2004/07/Leftouch.Data.Summary" />

Часть configuration.svcinfo:

<endpoint normalizedDigest="&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-16&quot;?&gt;&lt;Data address=&quot;http://localhost:60322/AccountManager.svc&quot; binding=&quot;customBinding&quot; bindingConfiguration=&quot;CustomBinding_AccountManager&quot; contract=&quot;AccountManager.AccountManager&quot; name=&quot;CustomBinding_AccountManager&quot; /&gt;" digest="&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-16&quot;?&gt;&lt;Data address=&quot;http://localhost:60322/AccountManager.svc&quot; binding=&quot;customBinding&quot; bindingConfiguration=&quot;CustomBinding_AccountManager&quot; contract=&quot;AccountManager.AccountManager&quot; name=&quot;CustomBinding_AccountManager&quot; /&gt;" contractName="AccountManager.AccountManager" name="CustomBinding_AccountManager" />

Часть Reference.svcmap:

</ClientOptions>
  <MetadataSources>
    <MetadataSource Address="http://localhost:60322/AccountManager.svc" Protocol="http" SourceId="1" />
  </MetadataSources>
  <Metadata>
    <MetadataFile FileName="AccountManager2.xsd" MetadataType="Schema" ID="e473b2d5-7af3-4390-87c3-a4fc3f54fb96" SourceId="1" SourceUrl="http://localhost:60322/AccountManager.svc?xsd=xsd2" />
    <MetadataFile FileName="AccountManager1.xsd" MetadataType="Schema" ID="fd3a1ae0-b38b-4586-8622-5b0ee07e39fb" SourceId="1" SourceUrl="http://localhost:60322/AccountManager.svc?xsd=xsd0" />
    <MetadataFile FileName="AccountManager.xsd" MetadataType="Schema" ID="6a49ee64-6eac-40e2-bcff-26418435e777" SourceId="1" SourceUrl="http://localhost:60322/AccountManager.svc?xsd=xsd1" />
    <MetadataFile FileName="AccountManager.disco" MetadataType="Disco" ID="9ec9a8cc-0cf0-4264-a526-b5a6c08f7d36" SourceId="1" SourceUrl="http://localhost:60322/AccountManager.svc?disco" />
    <MetadataFile FileName="AccountManager1.wsdl" MetadataType="Wsdl" ID="54a5b2c0-9d0e-4043-a7e4-d27ae6674bfc" SourceId="1" SourceUrl="http://localhost:60322/AccountManager.svc?wsdl=wsdl0" />
    <MetadataFile FileName="AccountManager.wsdl" MetadataType="Wsdl" ID="f8923013-3a6c-412b-b7da-bee5a5a7bb64" SourceId="1" SourceUrl="http://localhost:60322/AccountManager.svc?wsdl" />

.. и ВСЕ эти снова для других 2 служб тоже.

Я не являюсь мастером веб-сервисов / привязок / конечных точек / контрактов на операции или каких-либо связанных вещей. Я просто хочу, чтобы моя полностью уже работающая система (когда URI жестко задан) работала для относительных URI, это все, что мне нужно. Там должно быть простое решение. Может кто-нибудь объяснить, что точно напоминает эти типы файлов и декларации, которые важны, а какие необязательны, и как я могу создавать динамические ссылки на сервисы в самой чистой форме. Пожалуйста, с объяснениями. Я уже видел много постов и статей о динамических привязках и ссылках на сервисы, но, честно говоря, все запуталось, и я ничего не понял из этого. Любая конструктивная критика и решения приветствуются.

1 Ответ

2 голосов
/ 27 августа 2011

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

Обновите конечную точку в файле конфигурации службы, чтобы использовать либо полный адрес на этом компьютере (т. Е. http://somname.com/service.svc), либо задайте для baseAddresses в файле конфигурации имя машины.

Кроме того, если вы используете WCF 4.0 (VS 2010 / .NET 4.0), вы можете сделать так, чтобы WCF создал конечную точку по умолчанию для ваших служб, полностью исключив конечные точки из файла конфигурации (насколько я понимаю - сейчас мы просто переходим на 4.0 на работе, поэтому я не играл с новыми функциями).

ИЗМЕНЕНО ДЛЯ ДОБАВЛЕНИЯ

Новый подход, та же основная идея (что URI импортируется откуда-то). Исходя из ваших комментариев ниже, похоже, что конфигурация вашего сервиса настроена нормально, без жестко закодированных URI, указывающих на localhost.

Когда вы перемещаете свое приложение на целевой сервер (-ы), обновляете ли вы также свою ссылку на свою службу (с помощью Добавить ссылку на службу) или просто перемещаете файлы, которые генерируются из вашего локального ящика, на целевой сервер?

Если да, мне интересно, может ли это быть источником вашей проблемы. Я бы подумал , что указание адреса службы при создании клиента должно переопределять что-либо в файлах, связанных с WSDL, но, возможно, это не так.

Что-то попробовать:

Удалите раздел <client> из своего Web.config. Затем, когда вы создаете клиент, сделайте так:

fileManager = new FileManagerClient(new BasicHttpBinding("CustomBinding_FileManager"), new EndpointAddress("http://" + Settings.Host + "/FileManager.svc"));

Убедитесь, что вы передали имя раздела конфигурации привязки в конструкторе BasicHttpBinding, иначе вы получите привязку со значениями по умолчанию, а не с большими значениями, которые вы указали.

Идея заключается в том, чтобы исключить любую вероятность того, что настройки файла конфигурации клиента переопределяют то, что вы передаете при создании FileManagerClient.

Я бы посоветовал обновлять справочную информацию о сервисах для каждого развертывания на каждом отдельном сервере менее чем идеально - то, что вы пытаетесь выполнить, имеет смысл. Я делаю нечто подобное в написанном мной n-уровневом приложении - единственное отличие состоит в том, что я не использую ссылки на сервисы, я генерирую прокси-сервер через SvcUtil, а затем генерирую каналы через ChannelFactory<T>, что является еще одним маршрутом, который вам может понадобиться смотреть.

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

...