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

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

Когда я пытаюсь вызвать обновление, я получаю всевозможные странные ошибки, от «Socket Forcically Closed» до «Invalid Type» и другие странные сообщения. Если закомментировать 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>

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

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

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

Спасибо.

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

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

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

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

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

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

Спасибо!


person Jason Stevenson    schedule 13.04.2011    source источник
comment
Кроме того, я должен уточнить, когда я пишу как часть клиента, так и часть услуги. Каждый из них является отдельным плагином в приложении Rhino, поэтому я предполагаю, что технически я не являюсь самостоятельным хостингом.   -  person Jason Stevenson    schedule 15.04.2011


Ответы (2)


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


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

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

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

  • Создайте проект библиотеки классов для ваших сущностей / dtos. Поделитесь с клиентом.
  • Создайте проект библиотеки классов для сервисных интерфейсов. Поделитесь с клиентом.
  • Создайте проект библиотеки классов для реализации вашего сервиса. Остается только на сервере.
  • Клиент использует ChannelFactory<T> для создания фабрики, а затем создает прокси, вызывая CreateChannel()
person Aliostad    schedule 13.04.2011
comment
Простите мое незнание, я новичок в Wcf. Таким образом, вы говорите, что нужно просто ссылаться на интерфейсы как в клиентском, так и в серверном приложениях. И развернуть фабрику каналов для данной службы, а затем указать ее конечную точку в коде? - person Jason Stevenson; 14.04.2011
comment
Нет, вам все равно придется настраивать вручную, но, надеюсь, вы сделаете это один раз и в процессе узнаете больше о настройке. Вы можете использовать SvcConfigEditor.exe, чтобы помочь вам с настройкой. - person Aliostad; 14.04.2011
comment
Одна из причин, по которой мы переходим на эту архитектуру, заключается в том, чтобы полностью отделить наш пользовательский интерфейс от движка САПР, от которого он зависит. Нас вызывают в качестве подключаемого модуля к движку, поэтому в настоящее время у нас есть ссылки глубоко в движок САПР. Это вызывает множество проблем с Expression Blend (наш пользовательский интерфейс находится в Wpf). Если я переключусь на этот метод, не потеряю ли я прокси-классы, которые я смог использовать для переноса некоторых типов САПР в наш пользовательский интерфейс? - person Jason Stevenson; 14.04.2011
comment
Поступая таким образом, вы никогда не потеряете разделения забот. Собственно прокси-классы вам больше не нужны. Помните, что, разделяя интерфейс службы (контракт) и сущности (сообщения), вы приносите столько же, сколько WSDL / ссылка на службу. Я присоединился к компании, в которой работаю, и они давали рекомендации по обслуживанию, и каждый раз, когда что-то менялось, происходил хаос. Я изменил его на совместное использование библиотек, и теперь все стало прозрачно и легко. - person Aliostad; 14.04.2011
comment
Должны ли мы также писать нашу собственную асинхронную логику? Ничего страшного, я просто никогда не использовал способ работы Channel Factory. - person Jason Stevenson; 14.04.2011
comment
Сейчас переписываю ... Если получится, отмечу ваш ответ. Я надеюсь, что сделаю это в ближайший час. Спасибо чувак! - person Jason Stevenson; 14.04.2011
comment
Да, асинхронность - это то, что вы теряете. Наверное, единственное, на что стоит обратить внимание. - person Aliostad; 14.04.2011
comment
Без проблем, надеюсь помог. Это определенно сработало для меня и нашей компании ... надеюсь, что это сработает и для вас. - person Aliostad; 14.04.2011
comment
Итак, учитывая этот метод, тогда я должен настроить конечные точки для ServiceHost полностью в коде? Или я все еще что-то упускаю? - person Jason Stevenson; 14.04.2011
comment
Я бы также использовал конфигурацию для сервера. - person Aliostad; 14.04.2011
comment
@Aliostad У меня это успешно работает! Спасибо за ваше руководство, с тех пор я пошел и прочитал книгу WCF Джувала Лоури, в которой рассказывается об этом методе. Я также перешел на NamedPipes, так как общаюсь только через один и тот же компьютер. - Джейсон - person Jason Stevenson; 14.04.2011
comment
@Aliostad, я думаю, мне нужно вернуться к использованию класса Proxy. У меня масса проблем с получением определенных методов для работы с обновленным пользовательским интерфейсом. Я перепробовал все идеи SynchronizationContext, предложенные моим Juval, но, похоже, ничего не работает. По какой-то причине прокси-класс, созданный Visual Studio, просто работал у нас. За исключением ограничения MEX, который, я думаю, я могу реорганизовать контракты на отдельные классы, чтобы ограничить их количество. Есть ли у вас какие-либо предложения или вы когда-нибудь пытались вызвать методы, которые обновляют пользовательский интерфейс через службы Wcf, созданные методами CreateChannel ()? - person Jason Stevenson; 15.04.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();

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

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

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

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

person Jason Stevenson    schedule 15.04.2011