Как я могу обойти ограничение Договора на обслуживание для службы WCF при вызове "Обновления справочной службы" в VS 2008

У меня проблемы с одним Сервисом 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>

Мне нужно иметь возможность сгенерировать прокси-класс, нажав на ссылку Service Update, которая хорошо работала последние 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 ответа

Решение

У меня снова работает Справочник службы обновлений как из 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. Спасибо за помощь.

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


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

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

Это требует от вас:

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