Как стать автором
Обновить

Комментарии 71

В этой статье я расскажу о различных приемах разработки SOAP веб-сервисов по технологии ASMX, а также об этой технологии в целом. Кроме SOAP, также будет рассмотрена реализация AJAX. Статья будет полезна как тем, кто уже знаком с ней, так и тем, кто только собирается создать свой первый веб-сервис.
Закапывают это SOAP, закапывают (google еще в 2006 отказался от SOAP в своих сервисах), но всё равно периодически нет-нет, да кто-нибудь этот SOAP откопает.
А смысл его закапывать то? Для B2B сектора самое то
Во-первых, basicHttpBinding это полностью совместимый аналог asmx для WCF. Во-вторых, для b2b немаловажную роль играет производительность и поддержка, Web API и WCF — вот правильные направления.
Не увидел противоречия, что ASMX работает через SOAP, что WCF работает через SOAP.
P.S. Чтобы не было холивара, последние 6 лет я только через WCF работаю ;)
Не соглашусь, SOAP играет в наше время очень большую роль. Его главный плюс — максимально широкая интероперабельность.
Проблема в том, что он очень сильно переусложнён и никто вообще не умеет толком этот SOAP готовить. В результате все клиентские библиотеки для SOAP с большинством SOAP-сервисов из коробки не работают — надо подпиливать напильником. И плюс ещё большой оверхэд — мы передаём 100 байт данных и к нему — два килобайта XMLя, из которого килобайт WS-Addressing'а дублирует HTTP-заголовки. Чудесная технология.
WS-Addressing как бы не обязателен для использования, хотя его зачем-то всюду включают
Ну, в одном из наших случаев он был обязателен и эти тэги даже подписывались цифровой подписью ГОСТовыми алгоритмами (а XML-DSig по нескольким нодам — это уже килобайт 5 к оверхеду). А если заглянуть в <soap:Body>, то взору открывался небольшая вложенность из тэгов, внутри которой Base64 строка, раскодировывающаяся в другой XML, внутри тэгов которого значения в жутком и древнем формате, созданном примерно тогда, когда создатели XML только родились. WSDL? Ну, он был, но он описывал только верхний уровень, до Base64. Примеры рабочих запросов были чем-то вроде народных сказок — они у всех были и у всех они были разными. Пытаться использовать какие-то библиотеки для этого никто даже не пытался — были шаблоны, которые заполнялись, рендерились, кодировались, результат подавался в другой шаблон, тот рендерился, подписывался и просто POSTился на endpoint. Говорят, оно и посейчас работает.
О, какая знакомая картина. Я бы даже контрагента предположил, но смысла нет — не одиноки они, нет.

С другой стороны, такие люди из любого стандарта такое делают. Это просто способ мышления.
Ну, если кто-то так делает — это совсем не является «недостатком SOAP»
Очень многие так делают. Да так, что в результате от одного только слова «SOAP» начинаешь вздрагивать.
А еще многие запихивают внутрь строкового литерала JSON другой JSON. Но я же не вздрагиваю от слова JSON? :)
О да, я как-то весь вечер убил, убеждая человека, что REST ≠ JSON. Задача была простой — у нас был генерённый не нами страшный XML (SOAP-конверт, кстати), который мы дозаполняли, подписывали и отправляли на некий endpoint, но тут нужно было передать его стороне того человека, а они бы у себя просто сохраняли бы этот XML в файл «как есть». Человек на полном серьёзе предлагал паковать XML в Base64 и запихивать в строку внутрь JSON. Я протестовал: «Давай я просто XML POST'ом зашлю, зачем городить очередной Base64?». Но в их Java-мире, видимо, есть проблемы, если XML пересылать «как есть», и убеждение проходило плохо, но проходило. У человека на том конце искрило, и он возражал: «Но ведь это получится SOAP, а не REST!». «Ну да, но ведь это всё равно REST! Метод POST?» — «POST…», «В теле данные?» — «Данные…». Дискуссия была весёлой, а моя цель корыстной — ведь если бы я убедил человека, то мне не пришлось бы вносить изменений в код специально для них (можно было просто вписать другой endpoint в админке) ну и мир бы стал чуточку лучше. И убедил.
searchsoa.techtarget.com/definition/REST

REST (REpresentational State Transfer) is an architectural style, and an approach to communications that is often used in the development of Web services. The use of REST is often preferred over the more heavyweight SOAP (Simple Object Access Protocol) style because REST does not leverage as much bandwidth, which makes it a better fit for use over the Internet. The SOAP approach requires writing or using a provided server program (to serve data) and a client program (to request data).
Они с любой технологией так делают. Поэтому в какой-то момент вздрагиваешь от названия интегратора/проекта или слов «обмен документами»/«универсальный механизм».
Я бы даже расширил это до проблемы «несовместимости» клиентских И серверных библиотек (из-за переусложненности, как вы заметили, и «неоднозначностях» в спецификации)
Если у вас SOAP сервер MS и клиент на .NET — все (возможно) будет работать по накатанной (как у автора в статье). Но если, не дай бог, у вас другой Enterprise-сервер или клиент (Java например), или, упаси господи, PHP\Python… тут пиши пропало.
Постоянная тема переписок с клиентами на разных платформах —
— «У нас все падает при парсинге вашего WSDL, похоже что проблема с неймспейсами...»
— «Но ведь наш WSDL генерируется автоматически супер-сервером таким-то...»
— «А что об этой проблеме пишут в спеке?»
— «А черт его знает, в спеке вроде упоминается что-то на эту тему, но как это правильно растолковать — хз».
— «Может давайте попробуем JSON-RPC?»
— «Что ж вы раньше то молчали...»
Занавес.
Вот вы как раз проиллюстрировали проблему «давайте запихнем супер-сервер». Нам тут с год назад прислали на вычитку проект некоторой интеграционной шины широкого применения, с универсальным (в смысле — одним и обязательным для всех клиентов) интерфейсом. И вот этот интерфейс зачем-то сделали на SOAP, при этом совершенно игнорируя те возможности, которые в нем есть, и сводя его к перекидке xml-пакетов.

На все вопросы «зачем, почему нельзя просто пакетами по http кидаться» ответа не было.
А пакеты у вас как положенно в string заворачивали? А то у нас была интеграция с одной компанией, с мировым именем. На SOAP. Все как надо. Все сообщения были строковыми параметрами в где в строках был XML с конвертами, внутри которых структуры описывались как <any />
Сходу не помню. У наших контрагентов лидировало два варианта: либо xs:any, либо BASE64, внутри которого отдельный xml.
Это всего лишь «несовместимость» настроек по умолчанию. За java-реализации не поручусь, но я готов на стороне WCF реализовать любой WSDL.

Даже если там CDATA с вложенным сообщением :) И потом все будет работать как по накатанной…

Хотя, конечно же, мне больше нравятся настройки по умолчанию.
Вы пробовали с SOAP-сервисами взаимодействовать из ванильного JavaScript?
SG: No. SOAP doesn’t really use HTTP response codes.

Dev: So, when you said SOAP uses HTTP, what you meant to say is SOAP tunnels over HTTP.

SG: Well, ‘tunnel’ is such an ugly word. We prefer to say SOAP is transport agnostic.

Dev: But HTTP isn’t a transport, it’s an application protocol. Anyway, what other “transports” does SOAP support?

SG: Well, officially none. But you can potentially support any of ‘em. And there’s lots of platforms that support JMS, and FTP, and SMTP.

Dev: Does anyone actually use these other transports?

SG: Uhm, no. But the point is you can.

Dev: Fine. How ’bout this SOAPAction HTTP header, what’s that for?

SG: To be honest, no one’s really sure.

harmful.cat-v.org/software/xml/soap/simple
Dev: Does anyone actually use these other transports?

SG: Uhm, no. But the point is you can.
Используют, еще как используют. Вот мы, к примеру, в одном проекте посылаем сообщения SOAP через очереди IBM WebSphere MQ (кстати, если будет выбор — не используйте эту технологию — там нет нормального клиента под .NET).
У нас в проекте (пусть и на Java) SOAP нигде не используется. Летают обычные xml или json через jms обычно. Или делается API и данные летают в бинарном виде через socket.
Вот не надо тут про «интероперабельность»: для того, чтобы создать хотя бы подобие оной, лучшие Энтерпрайз Архитекторы создали целое новое семейство стандартов WS-I поверх спецификации SOAP. И даже со всем этим багажом «нельзя просто так взять» и вызвать сколь-нибудь сложный .NET-сервис из Java-клиента (или наоборот) — обязательно что-нибудь где-нибудь да отъедет. И сиди потом разбирайся в хитросплетении многомудрых XML-элементов.
asmx — да же Microsoft везде пишет что это деприкейтед реализация
Пытался придумать, что можно сдлеать на asmx, чего нельзя сделать в wcf.
Про работу с Ajax — Web API лучше любого asmx
Не зря же автор написал, что ASMX — это отвертка, а WCF — мультитул.
Аналогия неверна в том смысле, что хорошая отвертка обычно удобнее для завинчивания, нежели мультитул (из реального опыта); но вот случаев, когда ASMX удобнее WCF, я теперь уже и не знаю.
Ну у меня была простенькая ASP.Net-страничка, где мне нужно было вызывать один серверный метод из джаваскрипта для пополнения дива. Мне было проще сделать один asmx-сервис с единственным методом, чем говордить WCF.
В рамках аналогии выше как раз asp.net оказывается мультитулом, одним из инструментов готорого (asmx) вы воспользовались тогда, когда вам стало лень идти за отверткой (wcf).

(хотя почему вы не взяли webapi — мне не очень понятно)
Был ограничен .Net 3.5
Статья хорошая. Спасибо автору.
Но здесь упущена очень удобная технология в плане AJAX.
Есть очень интересный параемтр GenerateScriptType, с помощью которого можно создавать типы данных JS.
Благодаря этому код на клеиенте становится более структурированым.

Так же есть возможность более простого вызова сервисов, как функций на клиенте.
Плюсы ASMX:
Легкость в разработке
Легкость в изучении
Нет «ада» конфигурирования


А можно для каждого описываемого вами плюса указать конкретное сравнение с WCF, на котором было бы видно, что WCF в этом параметре действительно слабее?
Для опытного разработчика не будет разницы между ASMX и WCF в сложности создания простого SOAP веб-сервиса. Но разницу почувствует начинающий. Я не говорю что WCF это «слишком сложно», я так не считаю, все относительно.
Итак, WCF – это «швейцарский нож» в области транспорта данных, а ASMX – «добротная отвертка». И лучше всего, конечно, уметь пользоваться обоими инструментами.
Я не вижу причин, зная WCF (и WebAPI), продолжать разрабатывать ASMX-сервисы. Можете их назвать? (легаси не считаем)
В обучающих целях, например.
Обучения кого и чему?
Обучения студентов основам SOAP.
Основам SOAP надо учить на заведомо работающем тестовом сервисе и xml-клиенте навроде SoapUI.

И нет, обучающие цели — это вообще не повод для разработки.
Со времен Simplified configuration ничего сложного в простейшем WCF SOAP-сервисе нет.
Люди, идите, пожалуйста, в ногу со временем, а если сами не хотите — школьников хотя бы не учите
Интересно сравнить, сколько веб-сервисов обоих типов видит Google: 314 000 ASMX и 6 280 WCF

Зашибись сравнение, особенно учитывая, что (а) ощутимое количество wcf-сервисов находится внутри защищенного периметра и гуглю не видно и (б) ни один из wcf-сервисов, разработанных мной за последние год-два, не откликается на путь *.svc
Никто не знает сколько точно ASMX и WCF веб-сервисов существует в интернете. Гугл видит лишь очень малую их часть, это просто грубая оценка популярности технологий.
Нет, это грубая оценка погоды на марсе.
Есть только одна проблема с новыми протоколами, предлагаемыми Microsoft…

Мир отнюдь не заканчивается на Microsoft Windows, VisualStudio и .NET.
Так что SOAP жив и будет жить. Как раз из за своей относительной простоты и уже наработанных библиотек и пр. для сред, отличных от .NET

А какие «новые протоколы» вы имеете в виду?

(особенно учитывая, что SOAP — тоже разработан с участием MS)
У нас вообще MS Windows на не используется на продакшен серверах.
И уже сталкивались, с тем, что на нашу просьбу «дайте описание протокола» нам давали кусок кода клиента на .NET 3.0 и говорили «Вот протокол — пользуйтесь».

А на просьбу «дайте wsdl» спрашивали «а что это такое?».

В общем я не верно выразился и не совсем то хотел сказать.
Не протоколы, как таковые, а то что программисты, пишущие под VS даже не подозревают, что мир не ограничен рамками Visual Studio (Кстати, ужасные и не переносимые исходники на C++ под VS получаются)
И какое отношение это имеет к статье и дискусии в ней?
Да прямого отношения не имеет.
Просто очень хотел бы увидеть если не статью, то хотя бы комментарии по использования SOAP не в среде VS и проблемы совместимости.

В этой статье я расскажу о различных приемах разработки SOAP веб-сервисов по технологии ASMX, а также об этой технологии в целом.

В статье, кстати, нет дискуссий. Это просто примеры.

Считаете, что дискуссия не нужна — значит не нужна.
В статье, кстати, нет дискуссий.

Я имею в виду дискуссию в комментариях к статье.
Дискуссия, которая открыта Вами, конкретно мне интересно «на посмотреть», но не интересна в прикладном смысле.
Вы lair, спорите (точнее троллите), что лучше ASMX или WCF. И то и другое — исключительно применимо в продуктах MS.
Сервис, разработанный под WCF, с большой вероятностью поддержит только клиент созданные в среде VS.
C поддержкой сервиса на ASMX (SOAP) проблем не будет.

Если Вы считаете, что это не принципиально — Ваше право. Мой опыт взаимодействия с через web-сервисы между разными организациями подсказывает другой.
Сервис, разработанный под WCF, с большой вероятностью поддержит только клиент созданные в среде VS.

Вы бы хоть разобрались в предмете, прежде чем писать. WCF, в первую очередь, дает SOAP-сервисы. Там, конечно, можно поменять транспорт и форматтер, но «из коробки» это SOAP. И да, у меня WCF-клиенты прекрасно потребляют сервисы, реализованные на java, а java-клиенты — потребляют наши WCF-сервисы. Именно потому, что SOAP.

Так что — мой опыт против вашего. Мой говорит, что в задаче интеграции нескольких систем (не важно, внутри организации или снаружи) WCF надежнее ASMX, потому что оба поддерживают SOAP, но WCF — существенно более зрелая технология, дающая больше контроля за происходящим.
Понятие разницы надежности между WCF и ASMX — это особенности реализации, которые снаружи (внешнему пользователю сервиса) зачастую не видны.
Ну какая разница, например, на каком движке скажем МТС выдает интерфейс для автоплатежей (хотя догадаться по косвенным признакам можно).

Если будет использоваться WCF в варианте SOAP+HTTP — снаружи никто разницу и не увидит.
В этом смысле — разницы нет. Если удобней разрабатывать с WCF — то пожалуйста.

Но чаще всего, прочему то начинают использовать не, как Вы сказали с «параметры из коробки», и тогда начинаются проблемы.

И вообще, я не сравнивал WCF и ASMX с точки зрения удобства и надежности.
Мне, как пользователю сервиса или как разработчику сервиса НЕ в среде VisaulStudio доступно только SOAP1.2+HTTP. Как только на «той стороне» начинают что то менять и играться с транспортным уровнем, то у меня возникают проблемы.
Про слова SOAP, xsd, wsdl и пр. зачастую разработчики сервисов под VisualStudio даже не знают. У них это все скрыто.

Вот ровно это, я имел в виду. Знать все уровни протокола просто надо. Не агитирую за кодирование на ассемблере собственного стека TCP/IP, но когда складываешь из кубиков, то нужно понимать что за этим скрывается.
Вы понимаете, но почему то считаете, что знание уровня SOAP не нужно.
Или, может быть, я не правильно понял…
Но чаще всего, прочему то начинают использовать не, как Вы сказали с «параметры из коробки»,

Откуда у вас такие сведения? Вы можете дать статистику?

Мне, как пользователю сервиса или как разработчику сервиса НЕ в среде VisaulStudio доступно только SOAP1.2+HTTP.

… а почему не SOAP1.1?

Про слова SOAP, xsd, wsdl и пр. зачастую разработчики сервисов под VisualStudio даже не знают. У них это все скрыто.

Извините, мне сложно обсуждать каких-то мифических — но, очевидно, некомпетентных — «разработчиков под VisualStudio», которые чего-то не знают. Могу вот поговорить про разработчиков под 1С и java (разные разработчики), которые не умеют пользоваться xsd в интеграционных решениях, основанных на SOAP.

Вы понимаете, но почему то считаете, что знание уровня SOAP не нужно.

Нет, я считаю, что не нужно изучать ASMX, потому что эта технология устарела, и есть другие технологии, позволяющие достичь тех же результатов.
Откуда у вас такие сведения? Вы можете дать статистику?

Мм… погорячился. Статистика как раз в обратную сторону. Но субъективно, из за уровня проблем и согласований… что бы убедить изменить/включить параллельно HTTP.

… а почему не SOAP1.1?

В основном потому, что это определяется партнерами у которых уже есть работающий сервис, к которому нужно подключится.
<wsdl:definitions… xmlns:soap12=«schemas.xmlsoap.org/wsdl/soap12/» ...wsdl/">
А в тех случая, когда мы свой сервис создаем, то для единобразия, после согласования с партнерами обычно SOAP 1.2
Других аргументов при выборе — нет.

Нет, я считаю, что не нужно изучать ASMX, потому что эта технология устарела, и есть другие технологии, позволяющие достичь тех же результатов.

Вообще то, я с этим даже не спорил! И не говорил, что нужно изучать ASMX.

Только если не путать конкретную технологию (набор библиотек, их описание и способа кодирования в VS) от Microsoft со стеком протоколов, включающих, в данном случае, SOAP.
В основном потому, что это определяется партнерами у которых уже есть работающий сервис, к которому нужно подключится.

Ну то есть это не «вам не доступно», а «вы не реализуете». Вот и выяснилось.

Вообще то, я с этим даже не спорил!

Вот мне и интересно, с чем вы спорите. Я вас прямо в первом комментарии об этом и спросил.
Эпический манускрипт по помирающей технологии.
В своё время (когда больше ничего не было и в среде разработок все, как полоумные носились с XML, утверджая, что "за ним будущее и вообще скоро всё будет в XML!") это была хорошая попытка унять разношёрстные реализации и сделать некий стандарт.
Вот только проблема закралась в том, что вы не найдёте двух библиотек на разных платформах, которые его одинаково реализуют. Грабли и костыли будут в любой паре. А если плясать в рамках одной платформы, то зачем вся эта убер-избыточность и переусложнённость?
В общем был такой, претендовал на универсальность, но пока к ней шёл — поезд уехал далеко вперёд. Сейчас разве что в каких-нибудь монструозных корпоративных проектах, которые никто не будет переписывать, и где нужна мифическая "интероперабельность", которую там никто на самом деле никогда не видел.
Как раз стоит задача, чтобы сайт через веб-сервис мог подключаться к древней базе заказчика.

К базе можно подключиться через OLE объект.

Может ASMX принять запрос SOAP, создать OLE объект, вернуть результат и самое-самое главное: запомнить OLE-объект, чтобы повторно его не создавать на следующих SOAP запросах?

Создание OLE-объекта — это фактически запуск нового приложения. Занимает у нас 3 секунды.

В пункте 15 вы писали про кеширование. Подойдет ли это к OLE объектам?
Может, но будет болезненно — вам придется повозиться с настройками, чтобы веб-приложение, где размещен сервис, не уходило в спячку (иначе будете терять кэш). Несколько проще будет создать self-hosted WCF, запущенный под windows-сервисом, потому что там жизненный цикл будет определяться сервисом.
Недостаточно информации, чтобы найти подходящее решение.
Объект HttpContext.Cache используется чтобы на некоторое время запомнить данные, которые потом автоматически очистятся.

Возможно тут надо использовать HttpApplicationState — данные в нем хранятся глобально и постоянно (но очищаются при
перезапуске приложения). А инициализировать их можно в Application_Start в global.asax — методе, который срабатывает при каждом запуске приложения.
Спасибо за статью.
Очень бы хотелось увидеть аналогичный пост о WCF.
Спасибо за отзыв и пожелание. Но про WCF я вряд ли напишу, так как по нему и так очень много актуальной информации.
Как автор данной старой статьи добавлю сюда ссылку на библиотеку для логирования SOAP под WCF.
https://github.com/capslocky/WcfSoapLogger
Я написал ее для одного из прошлых проектов. Вижу, что сюда все еще идет хороший трафик ) будут вопросы — пишите.
  1. Выглядит так, как будто ваша библиотека не может работать одновременно и как клиент, и как сервис. Зачем вообще нужна настройка Settings.IsService?


  2. При создании LoggingEncoderFactory вы передаете строку "text/xml". Это, скорее всего, окажется ошибкой если вы попытаетесь логировать SOAP 1.2. Надо бы свойство LoggingEncoder.MediaType делегировать _innerEncoder вместо того чтобы хардкодить.


  3. Почему вы даже не пытаетесь ничего залогировать в потоковом режиме?



PS Ну и последнее. Намного же проще логировать сообщения через поведение (Behavior), просто добавляя элемент в коллекцию MessageInspectors на этапах ApplyDispatchBehavior и ApplyClientBehavior

1. Может. Через конфиг она подключается как к service endpoint, так и к client endpoint. Поле 'Settings.IsService' — на самом деле не является настройкой, библиотека сама его вычисляет динамически для собсвтенных нужд. Похоже, более удачным было бы использовать слово 'Parameters'. Вот тут и тут происходит определение режима endpoint'a.

2. Хм, и правда, Content-Type может быть другим, надо переделать.

3. Потоковый режим работы для WCF не является дефолтным режимом. А в самой библиотеке идет оперирование сообщениями целиком, так как она парсит XML с целью извлечения operation name и его форматирования. Но замечение хорошее.

4. Да, логирование с помощью IDispatchMessageInspector (IClientMessageInspector) гораздо тривиальнее. Но на том проекте этот подход был бесполезен — на сервис иногда приходили символы с некорректной кодировкой, десериализация падала, и до Behavior исполнение просто не доходило. Поэтому пришлось спуститься на уровень ниже, чтобы увидеть реальное содержимое некорректного запроса. Фактически MessageInspector не видит самого запроса/ответа, ему дается xml-результат после десериализации + сериализации.

  1. Может.

Нет, не может. Потому что объект Settings — разделяемый между всеми энкодерами, и его свойство IsService не может принимать значение true и false одновременно. Возможно, вам просто везло.

Я имею в виду вот что. Пусть дано: self-hosted wcf web-service, и из того же приложения идут клиентские запросы на 2 внешних веб-сервиса и мы хотим залогировать все 3 endpoint. Тогда конфиг будет вылядить вот так:
Скрытый текст
<bindings>
  <customBinding>
    <binding name="soapLoggerBinding_XXX">
      <soapLoggerMessageEncoding_X logPath="C:\SoapLog\X\Service" saveOriginalBinaryBody="false" useCustomHandler="false" />
      <httpTransport />
    </binding>
     <binding name="soapLoggerBinding_YYY">
      <soapLoggerMessageEncoding_Y logPath="C:\SoapLog\Y\Client" saveOriginalBinaryBody="false" useCustomHandler="false" />
      <httpTransport />
    </binding>
    <binding name="soapLoggerBinding_ZZZ">
      <soapLoggerMessageEncoding_Z logPath="C:\SoapLog\Z\Client" saveOriginalBinaryBody="false" useCustomHandler="false" />
      <httpTransport />
    </binding>
  </customBinding>
</bindings>


<extensions>
  <bindingElementExtensions>
    <add name="soapLoggerMessageEncoding_X" type="WcfSoapLogger.EncodingExtension.LoggingExtensionElement, WcfSoapLogger" />
    <add name="soapLoggerMessageEncoding_Y" type="WcfSoapLogger.EncodingExtension.LoggingExtensionElement, WcfSoapLogger" />
    <add name="soapLoggerMessageEncoding_Z" type="WcfSoapLogger.EncodingExtension.LoggingExtensionElement, WcfSoapLogger" />
  </bindingElementExtensions>
</extensions>


А теперь попробуйте, как и все нормальные люди, использовать общий биндинг и для запросов и для ответов — и удивитесь результату.


PS ну ладно, вы биндинги разделили чтобы указать разный logPath. Но зачем вы создали три одинаковых bindingElementExtension?!

Ну, мне такой вариант даже в голову не приходил, так как для меня очевидно, как надо правильно подключать мой кастомный энкодер.
Да, перемудрил, bindingElementExtension достаточно 1 раз описать.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории