Как я могу обойти ограничение Договора на обслуживание для службы 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()