Как я могу обойти ограничение Договора эксплуатации службы WCF при вызове «Обновить ссылку на службу» в VS 2008 - PullRequest
1 голос
/ 14 апреля 2011

У меня проблемы с одним сервисом Wcf, который есть у нас в приложении. В нем около 150 [OperactionContract]. Теперь я не могу Обновление справочника услуг в Visual Studio 2008.

Я получаю всевозможные странные ошибки, варьирующиеся от «принудительно закрытого гнезда» до «неверный тип» и другие странные сообщения, когда я пытаюсь вызвать обновление. Если я закомментирую 10-20 операций, все будет нормально.

Я читал всевозможные посты здесь, на MSDN и во многих блогах. Все они указывают на конфигурации привязки, которые необходимо изменить, либо в основной привязке, либо в привязке MetadataExchange.

Моя проблема в том, что я попробовал все это и до сих пор не смог заставить его работать надежно.

Я сам размещаю службу в приложении, и это же приложение также является клиентом. Они используют один и тот же файл конфигурации (в настоящее время), потому что мы находимся в процессе разбиения приложения на 2 части через уровень сервиса Wcf.

Вот отрывок, показывающий мои привязки, которые я определил:

<system.serviceModel>

    <bindings>
      <netTcpBinding>
        <binding name="NetTcpBinding_IRhinoServices"
                 closeTimeout="00:05:00"
                 openTimeout="00:05:00"
                 receiveTimeout="00:15:00"
                 sendTimeout="00:05:00"
                 transactionFlow="false"
                 transferMode="Buffered"
                 transactionProtocol="OleTransactions"
                 hostNameComparisonMode="StrongWildcard"
                 listenBacklog="100"
                 maxBufferPoolSize="2147483647"
                 maxBufferSize="2147483647"
                 maxConnections="100"
                 maxReceivedMessageSize="2147483647">
          <readerQuotas maxDepth="2147483647"
                        maxStringContentLength="2147483647"
                        maxArrayLength="2147483647"
                        maxBytesPerRead="2147483647"
                        maxNameTableCharCount="2147483647" />
          <reliableSession ordered="true"
                           inactivityTimeout="00:10:00"
                           enabled="false" />
          <security mode="None">
          </security>
        </binding>
      </netTcpBinding>

      <customBinding>
        <binding name="customMex">
          <textMessageEncoding>
            <readerQuotas maxDepth="2147483647"
                          maxStringContentLength="2147483647"
                          maxArrayLength="2147483647"
                          maxBytesPerRead="2147483647"
                          maxNameTableCharCount="2147483647" />
          </textMessageEncoding>
          <tcpTransport transferMode="Buffered"
                        maxReceivedMessageSize="2147483647"
                        maxBufferSize="2147483647"/>
        </binding>
      </customBinding>

    </bindings>

    <client>
      <endpoint address="net.tcp://localhost:8523/RhinoServices"
                binding="netTcpBinding"
                bindingConfiguration="NetTcpBinding_IRhinoServices"
                contract="RhinoServicesReference.IRhinoServices"
                name="NetTcpBinding_IRhinoServices">
        <identity>
          <dns value="localhost" />
        </identity>
      </endpoint>
    </client>

    <services>
      <service behaviorConfiguration="CounterSketchServer.RhinoServicesBehavior"
               name="CounterSketchServer.RhinoServices">
        <endpoint address=""
                  binding="netTcpBinding"
                  contract="CounterSketchServer.IRhinoServices">
          <identity>
            <dns value="localhost" />
          </identity>
        </endpoint>

        <endpoint address="mex"
                  binding="customBinding"
                  contract="IMetadataExchange"
                  name=""
                  bindingConfiguration="customMex"
                  listenUriMode="Explicit" />

        <host>
          <baseAddresses>
            <add baseAddress="net.tcp://localhost:8523/RhinoServices" />
          </baseAddresses>
        </host>
      </service>
    </services>

    <behaviors>
      <serviceBehaviors>
        <behavior name="CounterSketchServer.RhinoServicesBehavior">
          <serviceMetadata httpGetEnabled="false" />
          <serviceDebug includeExceptionDetailInFaults="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>

  </system.serviceModel>

Мне нужно иметь возможность сгенерировать прокси-класс, нажав на ссылку «Служба обновления», которая хорошо работала последние 2 недели, пока я не достиг этого таинственного предела.

Большинство примеров, которые я видел, чтобы разрешить этот разговор о привязках http для mex, но я хотел бы придерживаться только netTcp, если это возможно, так как я сам хостинг.

Может кто-нибудь помочь мне?

Спасибо.

* ОБНОВЛЕНИЕ *

Я попробовал предложение @Aliostad, и сначала оно показалось мне удачным. Пока я не попробовал некоторые из наших вызовов Wcf, которые обновляют элементы интерфейса. Это сработало при использовании привязок NetTCP с прокси-классом, созданным инструментом Visual Studios (Add Service Reference). Но при использовании Channel Factory он не работает.

Я пытался просмотреть SyncrhonizationContext в книге WCF Джувала, но ничего, что я делал, казалось, не сработало.

Я пытался использовать как именованные каналы, так и NetTCP в качестве привязки для канала, который я создаю с помощью ChannelFactory, и они, похоже, ведут себя совершенно иначе, чем другие, связанные с длительными операциями Wcf, но ни одна из них не работает для обновления элементов пользовательского интерфейса.

Мои сервисы фактически работают в плагине для движка Rhino 3D CAD, и определенные вызовы (Render и т. Д.) Запускают пользовательский интерфейс в Rhino для обновления. Я предполагаю, что это вызывает проблему границы потока. Исключение, которое я получаю: попытка чтения или записи в защищенную память

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

Спасибо!

Ответы [ 2 ]

2 голосов
/ 14 апреля 2011

Прежде всего, я считаю, что единственное решение - удалить ссылку и снова добавить ее.


В качестве альтернативы, если вы владеете и Клиентом, и Службой - что, похоже, я получаюпрочитав ваш вопрос, который вы делаете - могу ли я настоятельно предложить вам поделиться своими сервисными интерфейсами со своими клиентами - вместо того, чтобы использовать ссылку на сервис?

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

Для этого вам необходимо:

  • Создать проект библиотеки классов для ваших сущностей / dtos.Поделитесь им с клиентом.
  • Создайте проект библиотеки классов для ваших сервисных интерфейсов.Поделитесь им с клиентом.
  • Создайте проект библиотеки классов для реализации вашей службы.Остается только на сервере.
  • Клиент использует ChannelFactory<T> для создания фабрики, а затем создает прокси, вызывая CreateChannel()
1 голос
/ 15 апреля 2011

У меня снова работает справочник службы обновлений как из SvcUtil.exe, так и из Visual Studio 2008.

Для этого я добавил следующий раздел в файлы конфигурации для devenv.exe.config и SvcUtil.exe.config :

<!-- CUSTOM MetaDataExchaning Binding to all for LARGE WCF Services -->

<client>
    <endpoint name="net.tcp" binding="netTcpBinding" bindingConfiguration="GenericBinding"
    contract="IMetadataExchange" />
    <endpoint name="http" binding="wsHttpBinding" bindingConfiguration="SecureBinding" contract="IMetadataExchange" />
</client>

<bindings>

    <netTcpBinding>
        <binding name="GenericBinding" maxBufferPoolSize="2147483647"
        maxReceivedMessageSize="2147483647" >
            <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647"
            maxArrayLength="2147483647" maxBytesPerRead="2147483647"
            maxNameTableCharCount="2147483647" />
            <security mode="None"/>
        </binding>
    </netTcpBinding>

    <wsHttpBinding>
        <binding name="SecureBinding" maxBufferPoolSize="2147483647"
        maxReceivedMessageSize="2147483647" >
            <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647"
            maxArrayLength="2147483647" maxBytesPerRead="2147483647"
            maxNameTableCharCount="2147483647" />
            <security mode="Message">
                <transport clientCredentialType="Windows" />
            </security>
        </binding>
    </wsHttpBinding>
</bindings>

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

        // DATA ENDPOINT
        NetTcpBinding binding = new NetTcpBinding(SecurityMode.Transport, true);
        Uri baseAddress = new Uri("net.tcp://localhost:8555/RhinoServices");
        _rhinoServicesHost = new ServiceHost(typeof(RhinoServices), baseAddress);
        _rhinoServicesHost.AddServiceEndpoint(typeof(IRhinoServices), binding, baseAddress);

        // META ENDPOINT
        BindingElement bindingElement = new TcpTransportBindingElement();
        CustomBinding customBinding = new CustomBinding(bindingElement);
        ServiceMetadataBehavior metadataBehavior = _rhinoServicesHost.Description.Behaviors.Find<ServiceMetadataBehavior>();
        if (metadataBehavior == null)
        {
            metadataBehavior = new ServiceMetadataBehavior();
            _rhinoServicesHost.Description.Behaviors.Add(metadataBehavior);
        }
        _rhinoServicesHost.AddServiceEndpoint(typeof(IMetadataExchange), customBinding, "MEX");

        _rhinoServicesHost.Faulted += RhinoServicesHost_Faulted;
        _rhinoServicesHost.Open();

Теперь я могу обновлять ссылки независимо от количества контрактов.

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

Так что, я думаю, мне все равно нужно это отследить ...

Также я нашел это решение по другому вопросу (нажмите для просмотра) , на который ответил @trendl. Спасибо за вашу помощь.

...