(MVC) MVC (2012 год)

Конфиги WCF-сервисов, обеспечивающие совместимость с JAVA, PHP, FLEX.

Сделать что-либо сложно - ума большого не надо. Мозги нужны чтобы сделать что-нибудь просто. В теме WCF все придумано чрезмерно сложно. Скажем стандартно клиент должен идентифицировать себя с помощью клиентского сертификата. Как-бы это кажется просто - и у меня действительно много сервисов, работающих именно так - вот тут пример установки такого сертификата для шлюза Инплата - Организация SSL транспортного уровня по программно загружаемому клиентскому сертификату. Фишка однако в том, что даже это несложное действие часто слишком сложно и требует высокой квалификации программистов и админов. Ну сделал это один раз человек с ЗП 150 тысяч в месяц, а через полгода сертификат прокис и (вдруг) в выходной день перед длительными праздниками перестали проходить платежи. Тот кто это когда-то сделал - уже давно где-нибудь в штатах. Дернулись на фриланс, дали удаленный доступ (вроде бы) специалисту - он немного поковырялся в реестре и все, конец. Теперь и тот специалист с доходом 150-200 тысяч в месяц уже никогда не восстановит жизнедеятельность фирмы. Не встречались пока с такой ситацией?

Поэтому делать надо просто, предельно просто, насколько возможно просто. Конечно, когда касается прохождения платежей - простота вредит - я об этом писал много раз (Шлюзы к платежным системам интернет-денег, Безопасность Web-приложений ) - во всех остальных случаях надо жертвовать безопасностью ради простоты.

WCF - предельно накрученая в плане сложности технология. Давайте скажем для начала, что основной кнфигурационный файл WCF-сервиса содержит 128 основных рабочих блоков (тегов первого уровня) - от ActionNotSupportedException до XPathMessageQuery и 37 основных пераметров-перечислений. Каждый из 128 блоков управления WCF верхнего уровня содержит десятки или сотни управляющих параметровю Ну например у WSHttpBinding (тег управления WCF верхнего уровня) имеется 22 основных рабочих режима, которые может установить администратор в конфиге и плюс 30 методов, которыми может пользоватся программист в коде. У ServiceHost - 17 основных свойств (режимов работы) и 55 методов работы для программиста. Примерно так же во всех остальных 128-ми блоках управления WCF. В каких-то сочетаниях это работает так, а в каких-то иначе. Понятно, что такие обьемы параметров, управляющих алгоритмами библиотеки WCF - System.ServiceModel.dll и System.ServiceModel.Web.dll никому в пользу не пойдут. Изучить сложное взаимодействие управляющих параметров и их влияние на алгоритмы в этих DLL - гораздо сложнее, чем написать с нуля самому эти же алгоритмы для свой собственной задачки. В общем, надо признать - индусы круто научились тащить из Билла-Дебила деньги.

В ряде случаев помоечный индустский код так и не удается настроить на совместимость например с Явой (несмотря на титанические усилия и массу убитого времени). Я об этом писал тоже уже много раз. И сделал свой собственный клиент WCF вместо всех этих индустских помоев - WCF_CLIENT - клиент Web-сервиса.

Для этого конечно надо понимать основные алгоритмы WCF. На мой взгляд делать web-сервисы исключительно для взаимодействия NET-NET или только для локалки - это маразм. Поэтому на самом верхнем уровне контроля алгоритмов WCF есть смысл выбирать только базовую или WS - привязки. Ну или MSMQ в тех редких случаях когда требуется отсоединенное отложенное взаиможействие между клиентом и сервисом. Кроме того, конечно нужна MEX-привязка (metadata exchange) - без нее WCF вырождается в полный маразм и превращается в простой обмен XML - я писал об этом тоже много раз - SOAP/WSDL vs XML data exchange. А в целом в WCF поддерживается 20 типов привязок.

У каждой привязки свои способы кодирования, свои способы обеспечения надежной или ненадежной доставки сообщений строго по очереди или произвольно, свои способы поддержки транзаккций (что-то поддерживается иногда, а что-то нет), свои возможные режимы работы сервиса - PerCall, Session, Singlton. Ну и миллион различных режимов (и их сочетаний) в плане безопасности - где-то что-то можно шифровать только на транспортном уровне, где-то возможен логин/пароль, в каких-то случаях клиентский сертификат, в каких-то электронный токен, в каких-то ацтентифкация кампутера. Обратные вызовы в каких-то случаях возможны, в каких-то нет, куки и совместимость с ASP.NET в каких-то сочетаниях параметров возможны, в каких-то нет.

Поэтому первой задачкой для любого программиста - как из всех этих индустских помоев - сделать себе рабочие конфигурации для тех или иных обычных случаев. Ну и при наличии необходимости усиления безопасности - начинать с этих контрольных точек двигатся дальше.

Итак, простейший конфиг для базовой привязки, совместимый с JAVA, FLEX и другими средами вы видите ниже. Это железно работающий минимальный конфиг WCF - разумеется вам надо вписать свои адреса сервисов и свои классы.


   1:  <?xml version="1.0" encoding="UTF-8"?>
   2:  <configuration>
   3:      <system.web>
   4:          <authentication mode="None" />
   5:          <customErrors mode="Off"/>
   6:          <compilation debug="true" strict="false" explicit="true" targetFramework="4.0" />
   7:      </system.web>
   8:      <system.serviceModel>
   9:          <standardEndpoints />
  10:          <services>
  11:              <service behaviorConfiguration="Behavior0" name="FlyService.TicketList">
  12:                  <endpoint address="http://flyservice.vb-net.com/TicketList.svc"
  13:                   binding="basicHttpBinding" bindingConfiguration="basicHttpBinding0"
  14:                   contract="FlyService.ITicketList" />
  15:              </service>
  16:              <service behaviorConfiguration="Behavior0" name="FlyService.CursUSD">
  17:                  <endpoint address="http://flyservice.vb-net.com/CursUSD.svc"
  18:                   binding="basicHttpBinding" bindingConfiguration="basicHttpBinding0"
  19:                   contract="FlyService.ICursUSD" />
  20:              </service>
  21:              <service behaviorConfiguration="Behavior0" name="FlyService.CityCountry">
  22:                  <endpoint address="http://flyservice.vb-net.com/CityCountry.svc"
  23:                   binding="basicHttpBinding" bindingConfiguration="basicHttpBinding0"
  24:                   contract="FlyService.ICityCountry" />
  25:              </service>
  26:          </services>
  27:          <bindings>
  28:              <basicHttpBinding>
  29:                  <binding name="basicHttpBinding0" />
  30:              </basicHttpBinding>
  31:          </bindings>
  32:          <behaviors>
  33:              <serviceBehaviors>
  34:                  <behavior name="Behavior0">
  35:                      <serviceMetadata httpGetEnabled="true" />
  36:                      <serviceDebug includeExceptionDetailInFaults="false" />
  37:                  </behavior>
  38:              </serviceBehaviors>
  39:          </behaviors>
  40:          <serviceHostingEnvironment multipleSiteBindingsEnabled="false" aspNetCompatibilityEnabled="false" >
  41:          </serviceHostingEnvironment>
  42:      </system.serviceModel>
  43:      <system.webServer>
  44:          <modules runAllManagedModulesForAllRequests="true" />
  45:          <defaultDocument>
  46:              <files>
  47:                  <add value="Default.aspx" />
  48:              </files>
  49:          </defaultDocument>
  50:      </system.webServer>
  51:  </configuration>

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


   1:  <?xml version="1.0" encoding="UTF-8"?>
   2:  <configuration>
   3:      <system.web>
   4:          <authentication mode="None" />
   5:          <customErrors mode="Off"/>
   6:          <compilation debug="true" strict="false" explicit="true" targetFramework="4.0" />
   7:      </system.web>
   8:      <system.serviceModel>
   9:          <client>
  10:              <endpoint address="http://flyservice.vb-net.com/CursUSD.svc"
  11:               binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding0"
  12:               contract="FlyService.ICursUSD" name="ClientEndpoin_CursUSD" />
  13:              <endpoint address="http://flyservice.vb-net.com/TicketList.svc"
  14:               binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding0"
  15:               contract="FlyService.ITicketList" name="ClientEndpoint_TicketList0" />
  16:              <endpoint address="http://flyservice.vb-net.com/CityCountry.svc"
  17:               binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding0"
  18:               contract="FlyService.ICityCountry" name="ClientEndpoint_CityCountry0" />
  19:          </client>
  20:          <standardEndpoints />
  21:          <services>
  22:              <service behaviorConfiguration="Behavior0" name="FlyService.TicketList">
  23:                  <endpoint address="http://flyservice.vb-net.com/TicketList.svc"
  24:                   behaviorConfiguration="" binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding0"
  25:                   contract="FlyService.ITicketList" />
  26:              </service>
  27:              <service behaviorConfiguration="Behavior0" name="FlyService.CursUSD">
  28:                  <endpoint address="http://flyservice.vb-net.com/CursUSD.svc"
  29:                   behaviorConfiguration="" binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding0"
  30:                   contract="FlyService.ICursUSD" />
  31:              </service>
  32:              <service behaviorConfiguration="Behavior0" name="FlyService.CityCountry">
  33:                  <endpoint address="http://flyservice.vb-net.com/CityCountry.svc"
  34:                   behaviorConfiguration="" binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding0"
  35:                   contract="FlyService.ICityCountry" />
  36:              </service>
  37:          </services>
  38:          <bindings>
  39:              <basicHttpBinding>
  40:                  <binding name="BasicHttpBinding0" closeTimeout="00:01:00"
  41:                  openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
  42:                  allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
  43:                  maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
  44:                  messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
  45:                  useDefaultWebProxy="true">
  46:                      <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
  47:                       maxBytesPerRead="4096" maxNameTableCharCount="16384" />
  48:                      <security mode="None">
  49:                          <transport clientCredentialType="None" proxyCredentialType="None"
  50:                           realm="" />
  51:                          <message clientCredentialType="UserName" algorithmSuite="Default" />
  52:                      </security>
  53:                  </binding>
  54:              </basicHttpBinding>
  55:          </bindings>
  56:          <behaviors>
  57:              <serviceBehaviors>
  58:                  <behavior name="Behavior0">
  59:                      <serviceMetadata httpGetEnabled="true" />
  60:                      <serviceDebug includeExceptionDetailInFaults="false" />
  61:                  </behavior>
  62:              </serviceBehaviors>
  63:          </behaviors>
  64:          <serviceHostingEnvironment multipleSiteBindingsEnabled="false" aspNetCompatibilityEnabled="false" >
  65:          </serviceHostingEnvironment>
  66:      </system.serviceModel>
  67:      <system.webServer>
  68:          <modules runAllManagedModulesForAllRequests="true" />
  69:      </system.webServer>
  70:  </configuration>

Как и первая конфигурация - эта конфигурация железно работает с любыми клиентами - PHP, FLEX, JAVA и проч. Ниже вы видите как этот сервис читается клиентом JAVA:



Однако, это самый убогий вариант WCF. В нем даже не обеспечивается поддержка последовательности вызовов службы из клиента. То есть более поздний пакет с вызовом из клиента службы может прийти раньше. На практике я сталкивался с этим сто раз. Например в базу пишется первой записью сначала ключ, а в следущем обращении некие данные, ссылающиеся на этот ключ. В итоге софт ИНОГДА падает. В тех случаях когда ключ попадает в базу позже чем данные, ссылающиеся на него. Ну а если софт делал крутой (программист - укрыватель исключений) - ИНОГДА некоторые записи будут пропадать. Ну типа - иногда все 1000 заказов попали в базу точно, а иногда 999, а иногда 990.

Это лишь один аспект работы WCF - а их (как мы видели выше) - 180 основных крупных блоков. Один из блоков - безопасность. Там тысячи режимов. Ну для примера в базовой привязке не поддерживается аутентификация по имени пользователя и пароля, а в привязке WS - она уже поддерживается. Ну и в этом конфиге никакая защита не обеспечивается - все передается открытым текстом. Зато базовая привязка совместима с ASMX-клиентами, а WS - только с клиентами следующих поколений.


   1:  <?xml version="1.0" encoding="UTF-8"?>
   2:  <configuration>
   3:      <system.web>
   4:          <authentication mode="None" />
   5:          <customErrors mode="Off"/>
   6:          <compilation debug="true" strict="false" explicit="true" targetFramework="4.0" />
   7:      </system.web>
   8:      <system.serviceModel>
   9:          <client>
  10:              <endpoint address="http://flyservice.vb-net.com/CursUSD.svc"
  11:               binding="wsHttpBinding" bindingConfiguration="wsHttpBinding0"
  12:               contract="FlyService.ICursUSD" name="ClientEndpoin_CursUSD" />
  13:              <endpoint address="http://flyservice.vb-net.com/TicketList.svc"
  14:               binding="wsHttpBinding" bindingConfiguration="wsHttpBinding0"
  15:               contract="FlyService.ITicketList" name="ClientEndpoint_TicketList0" />
  16:              <endpoint address="http://flyservice.vb-net.com/CityCountry.svc"
  17:               binding="wsHttpBinding" bindingConfiguration="wsHttpBinding0"
  18:               contract="FlyService.ICityCountry" name="ClientEndpoint_CityCountry0" />
  19:          </client>
  20:          <standardEndpoints />
  21:          <services>
  22:              <service behaviorConfiguration="Behavior0" name="FlyService.TicketList">
  23:                  <endpoint address="http://flyservice.vb-net.com/TicketList.svc"
  24:                   behaviorConfiguration="" binding="wsHttpBinding" bindingConfiguration="wsHttpBinding0"
  25:                   contract="FlyService.ITicketList" />
  26:              </service>
  27:              <service behaviorConfiguration="Behavior0" name="FlyService.CursUSD">
  28:                  <endpoint address="http://flyservice.vb-net.com/CursUSD.svc"
  29:                   behaviorConfiguration="" binding="wsHttpBinding" bindingConfiguration="wsHttpBinding0"
  30:                   contract="FlyService.ICursUSD" />
  31:              </service>
  32:              <service behaviorConfiguration="Behavior0" name="FlyService.CityCountry">
  33:                  <endpoint address="http://flyservice.vb-net.com/CityCountry.svc"
  34:                   behaviorConfiguration="" binding="wsHttpBinding" bindingConfiguration="wsHttpBinding0"
  35:                   contract="FlyService.ICityCountry" />
  36:              </service>
  37:          </services>
  38:          <bindings>
  39:              <wsHttpBinding>
  40:                  <binding name="wsHttpBinding0" closeTimeout="00:01:00" openTimeout="00:01:00"
  41:                   receiveTimeout="00:10:00" sendTimeout="00:01:00" bypassProxyOnLocal="false"
  42:                   transactionFlow="false" hostNameComparisonMode="StrongWildcard"
  43:                   maxBufferPoolSize="524288" maxReceivedMessageSize="65536" messageEncoding="Text"
  44:                   textEncoding="utf-8" useDefaultWebProxy="true" allowCookies="false">
  45:                      <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
  46:                       maxBytesPerRead="4096" maxNameTableCharCount="16384" />
  47:                      <reliableSession ordered="true" inactivityTimeout="00:10:00"
  48:                       enabled="false" />
  49:                      <security mode="None">
  50:                          <transport clientCredentialType="None" proxyCredentialType="None"
  51:                           realm="" />
  52:                          <message clientCredentialType="None" negotiateServiceCredential="false"
  53:                           establishSecurityContext="false" />
  54:                      </security>
  55:                  </binding>
  56:              </wsHttpBinding>
  57:          </bindings>
  58:          <behaviors>
  59:              <serviceBehaviors>
  60:                  <behavior name="Behavior0">
  61:                      <serviceMetadata httpGetEnabled="true" />
  62:                      <serviceDebug includeExceptionDetailInFaults="false" />
  63:                  </behavior>
  64:              </serviceBehaviors>
  65:          </behaviors>
  66:          <serviceHostingEnvironment multipleSiteBindingsEnabled="false" aspNetCompatibilityEnabled="false" >
  67:          </serviceHostingEnvironment>
  68:      </system.serviceModel>
  69:      <system.webServer>
  70:          <modules runAllManagedModulesForAllRequests="true" />
  71:      </system.webServer>
  72:  </configuration>

Увы, такая конфигурация (кажущаяся вполне разумной) - изумительно работает только с NET-клиентами. С NET-клиентами, ее можно расширять и гнуть в любую сторону. Однако стоит выйти за рамки NET - и начинаются проблемы. Альтова почему-то начинает пихать в POST-реквесты какие-то неадекватные заголовки - а Альтова в приницпе считается эталонным кроссплатформенным клиентом (понятно что микрософтовским клиентом нет никакого смысла даже тестировать WCF - все будет работать).



Ниже вы видите удачный протокол работы Altova с WCF-сервисом, сконфигурированным basicHttpBinding:



А вот здесь я изменил привязку с basicHttpBinding на wsHttpBinding - и тестовый кроссплатформенный клиент сразу же зглючило:



Хотя WSDL по прежнему читается тестовым клиентом XMLSPY:



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


   1:  <wsdl:definitions name="CursUSD" targetNamespace="http://tempuri.org/">
   2:      <wsdl:types>
   3:          <xsd:schema targetNamespace="http://tempuri.org/Imports">
   4:              <xsd:import schemaLocation="http://flyservice.vb-net.com/CursUSD.svc?xsd=xsd0" namespace="http://tempuri.org/"/>
   5:              <xsd:import schemaLocation="http://flyservice.vb-net.com/CursUSD.svc?xsd=xsd1" namespace="http://schemas.microsoft.com/2003/10/Serialization/"/>
   6:          </xsd:schema>
   7:      </wsdl:types>
   8:      <wsdl:message name="ICursUSD_GetCurs_InputMessage">
   9:          <wsdl:part name="parameters" element="tns:GetCurs"/>
  10:      </wsdl:message>
  11:      <wsdl:message name="ICursUSD_GetCurs_OutputMessage">
  12:          <wsdl:part name="parameters" element="tns:GetCursResponse"/>
  13:      </wsdl:message>
  14:      <wsdl:portType name="ICursUSD">
  15:          <wsdl:operation name="GetCurs">
  16:              <wsdl:input wsaw:Action="http://tempuri.org/ICursUSD/GetCurs" message="tns:ICursUSD_GetCurs_InputMessage"/>
  17:              <wsdl:output wsaw:Action="http://tempuri.org/ICursUSD/GetCursResponse" message="tns:ICursUSD_GetCurs_OutputMessage"/>
  18:          </wsdl:operation>
  19:      </wsdl:portType>
  20:      <wsdl:binding name="BasicHttpBinding_ICursUSD" type="tns:ICursUSD">
  21:          <soap:binding transport="http://schemas.xmlsoap.org/soap/http"/>
  22:          <wsdl:operation name="GetCurs">
  23:              <soap:operation soapAction="http://tempuri.org/ICursUSD/GetCurs" style="document"/>
  24:              <wsdl:input>
  25:                  <soap:body use="literal"/>
  26:              </wsdl:input>
  27:              <wsdl:output>
  28:                  <soap:body use="literal"/>
  29:              </wsdl:output>
  30:          </wsdl:operation>
  31:      </wsdl:binding>
  32:      <wsdl:service name="CursUSD">
  33:          <wsdl:port name="BasicHttpBinding_ICursUSD" binding="tns:BasicHttpBinding_ICursUSD">
  34:              <soap:address location="http://flyservice.vb-net.com/CursUSD.svc"/>
  35:          </wsdl:port>
  36:      </wsdl:service>
  37:  </wsdl:definitions>

А стоит изменить привязку с basicHttpBinding на wsHttpBinding - как WSDL резко меняется и его уже не опознают клиенты других платформ - JAVA, FLEX и проч.


   1:  <wsdl:definitions name="CursUSD" targetNamespace="http://tempuri.org/">
   2:      <wsp:Policy wsu:Id="WSHttpBinding_ICursUSD_policy">
   3:          <wsp:ExactlyOne>
   4:              <wsp:All>
   5:                  <wsaw:UsingAddressing/>
   6:              </wsp:All>
   7:          </wsp:ExactlyOne>
   8:      </wsp:Policy>
   9:      <wsdl:types>
  10:          <xsd:schema targetNamespace="http://tempuri.org/Imports">
  11:              <xsd:import schemaLocation="http://flyservice.vb-net.com/CursUSD.svc?xsd=xsd0" namespace="http://tempuri.org/"/>
  12:              <xsd:import schemaLocation="http://flyservice.vb-net.com/CursUSD.svc?xsd=xsd1" namespace="http://schemas.microsoft.com/2003/10/Serialization/"/>
  13:          </xsd:schema>
  14:      </wsdl:types>
  15:      <wsdl:message name="ICursUSD_GetCurs_InputMessage">
  16:          <wsdl:part name="parameters" element="tns:GetCurs"/>
  17:      </wsdl:message>
  18:      <wsdl:message name="ICursUSD_GetCurs_OutputMessage">
  19:          <wsdl:part name="parameters" element="tns:GetCursResponse"/>
  20:      </wsdl:message>
  21:      <wsdl:portType name="ICursUSD">
  22:          <wsdl:operation name="GetCurs">
  23:              <wsdl:input wsaw:Action="http://tempuri.org/ICursUSD/GetCurs" message="tns:ICursUSD_GetCurs_InputMessage"/>
  24:              <wsdl:output wsaw:Action="http://tempuri.org/ICursUSD/GetCursResponse" message="tns:ICursUSD_GetCurs_OutputMessage"/>
  25:          </wsdl:operation>
  26:      </wsdl:portType>
  27:      <wsdl:binding name="WSHttpBinding_ICursUSD" type="tns:ICursUSD">
  28:          <wsp:PolicyReference URI="#WSHttpBinding_ICursUSD_policy"/>
  29:          <soap12:binding transport="http://schemas.xmlsoap.org/soap/http"/>
  30:          <wsdl:operation name="GetCurs">
  31:              <soap12:operation soapAction="http://tempuri.org/ICursUSD/GetCurs" style="document"/>
  32:              <wsdl:input>
  33:                  <soap12:body use="literal"/>
  34:              </wsdl:input>
  35:              <wsdl:output>
  36:                  <soap12:body use="literal"/>
  37:              </wsdl:output>
  38:          </wsdl:operation>
  39:      </wsdl:binding>
  40:      <wsdl:service name="CursUSD">
  41:          <wsdl:port name="WSHttpBinding_ICursUSD" binding="tns:WSHttpBinding_ICursUSD">
  42:              <soap12:address location="http://flyservice.vb-net.com/CursUSD.svc"/>
  43:              <wsa10:EndpointReference>
  44:                  <wsa10:Address>http://flyservice.vb-net.com/CursUSD.svc</wsa10:Address>
  45:              </wsa10:EndpointReference>
  46:          </wsdl:port>
  47:      </wsdl:service>
  48:  </wsdl:definitions>

В общем лично у меня рабочий конфиг для wsHttpBinding - который бы железно работал на любой платформе - это пока открытый вопрос. В отдельных случаях я добиваюсь совместимости с клиентами других платформ - - предлагая клиенту несколько биндингов - чтобы он мог выбрать подходящий.

Ниже вы видете конфиг, в котором клиенту предлагается два биндинга - basicHttpBinding и customBinding. Этим конфигом мне неоднократно удалось добиваться совместимости со средой PHP. Это конфиг с отладкой (которая в данный момент выключена, чтобы не загаживать диск журналами).


   1:  <?xml version="1.0"?>
   2:  <configuration>
   3:      <connectionStrings>
   4:          <add name="SQLServer_ConnectionStrings" providerName="Npgsql"
   5:      connectionString="HOST=192.168.0.21;PORT=5432;PROTOCOL=3;DATABASE=inplat;USER ID=postgres;POOLING=True;CONNECTIONLIFETIME=0;MINPOOLSIZE=1;MAXPOOLSIZE=1024;COMMANDTIMEOUT=200;INTEGRATED SECURITY=False;" />
   6:      </connectionStrings>
   7:      <system.web>
   8:          <customErrors mode="Off"/>
   9:          <compilation debug="true" strict="false" explicit="true" targetFramework="4.0" />
  10:      </system.web>
  11:      <system.serviceModel>
  12:          <services>
  13:              <service behaviorConfiguration="dbg1" name="InplatGateway_SERV1.PaycashShopClient">
  14:                  <endpoint binding="basicHttpBinding" bindingConfiguration="PaycashShopServiceSoap"
  15:                   bindingNamespace="" contract="PaycashShopServiceSoap" />
  16:              </service>
  17:          </services>
  18:          <bindings>
  19:              <basicHttpBinding>
  20:                  <binding name="PaycashShopServiceSoap" closeTimeout="00:01:00"
  21:    openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
  22:    allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
  23:    maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
  24:    messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
  25:    useDefaultWebProxy="true">
  26:                      <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
  27:     maxBytesPerRead="4096" maxNameTableCharCount="16384" />
  28:                      <security mode="None">
  29:                          <transport clientCredentialType="None" proxyCredentialType="None"
  30:      realm="" />
  31:                          <message clientCredentialType="UserName" algorithmSuite="Default" />
  32:                      </security>
  33:                  </binding>
  34:              </basicHttpBinding>
  35:              <customBinding>
  36:                  <binding name="PaycashShopServiceSoap12">
  37:                      <textMessageEncoding maxReadPoolSize="64" maxWritePoolSize="16"
  38:     messageVersion="Soap12" writeEncoding="utf-8">
  39:                          <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
  40:      maxBytesPerRead="4096" maxNameTableCharCount="16384" />
  41:                      </textMessageEncoding>
  42:                      <httpTransport manualAddressing="false" maxBufferPoolSize="524288"
  43:     maxReceivedMessageSize="65536" allowCookies="false" authenticationScheme="Anonymous"
  44:     bypassProxyOnLocal="false" decompressionEnabled="true" hostNameComparisonMode="StrongWildcard"
  45:     keepAliveEnabled="true" maxBufferSize="65536" proxyAuthenticationScheme="Anonymous"
  46:     realm="" transferMode="Buffered" unsafeConnectionNtlmAuthentication="false"
  47:     useDefaultWebProxy="true" />
  48:                  </binding>
  49:              </customBinding>
  50:          </bindings>
  51:          <client>
  52:              <endpoint address="http://calc.vb-net.com/"
  53:      binding="basicHttpBinding" bindingConfiguration="PaycashShopServiceSoap"
  54:      contract="PaycashShopServiceSoap" name="PaycashShopServiceSoap" />
  55:              <endpoint address="http://calc.vb-net.com/"
  56:      binding="customBinding" bindingConfiguration="PaycashShopServiceSoap12"
  57:      contract="PaycashShopServiceSoap" name="PaycashShopServiceSoap12" />
  58:          </client>
  59:          <behaviors>
  60:              <serviceBehaviors>
  61:                  <behavior name="dbg1">
  62:                      <serviceMetadata httpGetEnabled="true" />
  63:                      <serviceDebug includeExceptionDetailInFaults="true" />
  64:                  </behavior>
  65:              </serviceBehaviors>
  66:          </behaviors>
  67:          <serviceHostingEnvironment multipleSiteBindingsEnabled="false" aspNetCompatibilityEnabled="true" />
  68:      </system.serviceModel>
  69:      <system.webServer>
  70:          <defaultDocument>
  71:              <files>
  72:                  <add value="PaycashShopClient.svc" />
  73:              </files>
  74:          </defaultDocument>
  75:          <modules runAllManagedModulesForAllRequests="true"  />
  76:      </system.webServer>
  77:   
  78:  </configuration>

Основная фишка этого конфига, обеспечивающая совместимость со средой PHP - привязка, которую я назвал PaycashShopServiceSoap12. Именно в режиме customBinding можно выставить несколько важных параметров, недоступных в стандартных режимах :



К счастью конфиг, создаваемый по умолчанию в Visual Studio (basicHttpBinding) - вполне достаточно хорошо совместим с немикрософтовскими средами - Создание асинхронного прокси для обращения к WCF средствами Adobe flex builder - здесь вы можете увидеть мою методику тестирования совместимости WCF-сервисов со средой FLEX.

А мою методику тестирования совместимости WCF-сервисов с тремя JAVA-стеками - Axis, CXF, Metro - вы можете посмотреть в моей заметке JAVA-клиенты Windows Communication Foundation.


А если вы пока начинающий программист и еще не понимате о какой совместимости вообще идет речь в этой заметке - почитайте пока как вообще строить WCF-сервисы - Как сделать SOAP/WSDL-вебсервис на ASP.NET/MONO для вызова его из FLEX.



Comments ( )
Link to this page: //www.vb-net.com/SimpleWCFconfig/index.htm
< THANKS ME>