(предупреждение - нечестивая смесь xml и бесплатной кодировки символов ниже.)
Короткая версия:
Почему я не могу получить свой справочный вызов службы (c #, .net 3.5, код автоматической ссылки на службу, добавленный в VS2008) для правильного кодирования параметра, который должен выглядеть следующим образом: (ищите "
биты .. .то моя проклятие.)
(другие дополнительные мыльные биты удалены для ясности)
<SOAP-ENV:Body><SOAPSDK4:SetCondition xmlns:SOAPSDK4="http://tempuri.org/message/">
<sharedSecret>buggerall</sharedSecret>
<xmlData><SEARCHINFO_LIST><SEARCH_INFO action="add" status=&
quot;3" name="TestProfile2" mask="0" campaign_id="33"
campaign_protected="N" condition_protected="N"><CONDITIONS/&
gt;<EXPRESSIONS/></SEARCH_INFO></SEARCHINFO_LIST></xmlData>
</SOAPSDK4:SetCondition></SOAP-ENV:Body>
Я устанавливаю параметр, звоню ... и служба возвращает приятное сообщение, говорящее: "НЕТ ТАК, МЫСЛИ ДЛЯ ВАС!"
Я попытался использовать несколько других форматов в строке параметров, передаваемых через веб-сервис:
action=\"add\"
который дал мне это по проводу (через фиддлер): action="add"
action="add"
который дал мне это по телеграфу: action=&quot;add&quot;
и различные комбинации (action = "" add ""?!) С html.encode, url.encode, которые почти либо полностью разбомблены, либо показаны в виде двойных кавычек на проводе.
О, и я даже попробовал <![CDATA["]]
окружающих. Это тоже не сработало.
Есть ли способ принудительно использовать двойную кавычку в бите innerHtml мыльного сообщения?
* (потому что так их хочет служба. Не задавайте вопросов. Это не те дроиды, которых вы ищете)
*
*
*
Длинная извилистая версия:
Я пишу приложение для автоматизации некоторых процедур, которые в настоящее время обрабатываются
(winform) административное приложение с графическим интерфейсом. (На самом деле, это MMC оснастки.
Так или иначе.)
Для выполнения своих задач приложение winform связывается с сервером через
стандартные вызовы веб-службы.
Я использую изящную VS2008 "ссылку на веб-сервис" для автоматического создания вещей
(это техническое описание), и я успешно прошел аутентификацию
веб-сервис. Чтобы убедиться, что я все делал правильно, я захватил
звонки из приложения с графическим интерфейсом, а затем сравнили их с тем, что я отправлял на
провод. Все было хорошо. Затем я столкнулся с пороками амперсанда. (Больше
правильно, как заставить вещи кодировать правильно)
Для одного из вызовов веб-служба ожидает увидеть что-то вроде этого:
(Я захватил приложение, отправив это через Fiddler)
<?xml version="1.0" encoding="UTF-8" standalone="no"?><SOAP-ENV:Envelope
xmlns:SOAPSDK1="http://www.w3.org/2001/XMLSchema" xmlns:SOAPSDK2="
http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAPSDK3="
http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="
http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Body><SOAPSDK4:SetCondition
xmlns:SOAPSDK4="http://tempuri.org/message/"><sharedSecret>0500001007C3525F3-F315-460D-
AF5C-D84767130126094</sharedSecret><xmlData><SEARCHINFO_LIST><SEARCH_INFO
action="add" status="3" name="TestProfile2" mask=&
quot;0" campaign_id="33"campaign_protected="N"
condition_protected="N"><CONDITIONS/><EXPRESSIONS/>&
lt;/SEARCH_INFO></SEARCHINFO_LIST></xmlData></SOAPSDK4:SetCondition></SOAP-
ENV:Body></SOAP-ENV:Envelope>
Извлечение всего дополнительного SOAP-y материала для отображения соответствующего бита - это раздел <xmlData>
, который передается. Обратите внимание на "
, окружающий параметры:
<SEARCHINFO_LIST><SEARCH_INFO action="add"
status="3" name="TestProfile2" mask="0"
campaign_id="33" campaign_protected="N"
condition_protected="N"><CONDITIONS/><EXPRESSIONS/>&
lt;/SEARCH_INFO></SEARCHINFO_LIST>
В моем коде у меня есть строка, построенная так:
var serviceParams = "<SEARCHINFO-LIST><SEARCH_INFO action=\"add\"
status=\"3\" name=\"TestProfileFromExternApp\" mask=\"0\" campaign_id=\"33\"
campaign_protected=\"N\"
condition_protected=\"N\"><CONDITIONS/><EXPRESSIONS/></SEARCH_INFO></SEARCHINFO_LIST>";
Когда мое приложение отправляет его по проводам, скрипач фиксирует это: (опять же,
убирая все мыло)
<SEARCHINFO-LIST><SEARCH_INFO action="add" status="3"
name="TestProfileFromExternApp" mask="0" campaign_id="33"
campaign_protected="N" condition_protected="N"><CONDITIONS/>
<EXPRESSIONS/></SEARCH_INFO></SEARCHINFO_LIST>
И принимающая служба отправляет обратно ошибку, которая ему не нравится. Он хочет "
d ## нит.
Правильно закодированы угловые скобки, но кавычки действительны в
Строка HTTP, и не кодируется.
"Ах-ха!" говорит я: «Я просто буду предварительно кодировать вещи вручную!». Я пытался
сделать что-то вроде этого:
var serviceParams = "<SEARCHINFO-LIST><SEARCH_INFO action="add"
status="3" name="TestProfileFromExternApp"
mask="0" campaign_id="33"
campaign_protected="N"
condition_protected="N"><CONDITIONS/><EXPRESSIONS/></SEARCH_INFO></SEARCHINFO_LIST>";
Который был разослан как (опять же через фидлер) и всем моим амперсандам (в
"
) конвертируется в &quot;
примерно так:
<SEARCHINFO-LIST><SEARCH_INFO action=&quot;add&quot;
status=&quot;3&quot;
name=&quot;TestProfileFromExternApp&quot; mask=&quot;0&quot;
campaign_id=&quot;33&quot; campaign_protected=&quot;N&quot;
condition_protected=&quot;N&quot;><CONDITIONS/><EXPRESSIONS/></SEARCH_INFO></SEARCHINFO_LIST>
И, как вы можете догадаться, принимающий веб-сервис вернулся с "BZZT!"
Спасибо за игру! ".
Я пробовал все виды escape и кодировать последовательности с похожими результатами.
По сути, после всех моих манипуляций он проходит что-то вроде
HttpUtility.HtmlEncode вправо , прежде чем выходить на провод, и любой
амперсанды в строке преобразуются в &
. И цитаты (одиночные или
double) игнорируются при конвертации. И принимающий веб-сервис
хочет те кавычки, представленные как "
преследуют его, или он собирается
возьми мяч и иди домой.
Моя последняя отчаянная надежда состояла в том, чтобы поймать сообщение правильно (я думал) перед тем, как оно поступило в провод, используя IClientMessageInspector для реализации проверки сообщения в событии BeforeSendRequest ... и вручную установить эти вещи, прежде чем он пошел на провод.
Я прекрасно фиксирую сообщение. Я могу даже вручную ввести "
.
Но когда его отправляют, и Wireshark, и Fiddler уверяют меня, что все идет хорошо отформатированным ... с кавычками, от которых я так отчаянно пытаюсь избавиться.
<xmlData xsi:type="xsd:string" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<SEARCHINFO-LIST><SEARCH_INFO action="add" status="3"
name="TestProfileFromExternApp" mask="0" campaign_id="33" campaign_protected="N"
condition_protected="N"><CONDITIONS/><EXPRESSIONS/>
</SEARCH_INFO></SEARCHINFO_LIST></xmlData>
Я в своем уме. Я приму любые предложения, включая пожертвование [маленькая приятная вещь] на алтаре [мерзкое божество] или продажу того же моего [душа / сердце / сын бионакла сбор] . Поверь мне, это будет меньшее зло.
В соответствии с запросом ниже, вот сгенерированная заглушка сообщения:
(Я думаю это то, что вы просили ...)
public int SetCondition(string sharedSecret, string xmlData, out string resultValue)
{
tzGui.tzCampaign.SetConditionRequest inValue = new tzGui.tzCampaign.SetConditionRequest();
inValue.sharedSecret = sharedSecret;
inValue.xmlData = xmlData;
tzGui.tzCampaign.SetConditionResponse retVal = ((tzGui.tzCampaign.CampaignSoapPort)(this)).SetCondition(inValue);
resultValue = retVal.resultValue;
return retVal.Result;
}
А вот как это называется:
void SetConditionTask()
{
//ok, now we *try* and create a new profile
var tzCampaignCxn = new tzCampaign.CampaignSoapPortClient("CampaignSoapBinding");
//no worky
//string xmlData = "<SEARCHINFO-LIST><SEARCH_INFO action=\"add\" status=\"3\" name=\"TestProfileFromExternApp\" mask=\"0\" campaign_id=\"33\" campaign_protected=\"N\" condition_protected=\"N\"><CONDITIONS/><EXPRESSIONS/></SEARCH_INFO></SEARCHINFO_LIST>";
//this one doesn't work
//string xmlData = "<SEARCHINFO-LIST><SEARCH_INFO action=<![CDATA[ " ]]>add<![CDATA[ " ]]> status=<![CDATA[ " ]]>3<![CDATA[ " ]]> name=<![CDATA[ " ]]>TestProfileFromExternApp<![CDATA[ " ]]> mask=<![CDATA[ " ]]>0<![CDATA[ " ]]> campaign_id=<![CDATA[ " ]]>33<![CDATA[ " ]]> campaign_protected=<![CDATA[ " ]]>N<![CDATA[ " ]]> condition_protected=<![CDATA[ " ]]>N<![CDATA[ " ]]>><CONDITIONS/><EXPRESSIONS/></SEARCH_INFO></SEARCHINFO_LIST>";
//this one doesn't either
string xmlData = "<SEARCHINFO-LIST><SEARCH_INFO action="add" status="3" name="TestProfileFromExternApp" mask="0" campaign_id="33" campaign_protected="N" condition_protected="N"><CONDITIONS/><EXPRESSIONS/></SEARCH_INFO></SEARCHINFO_LIST>";
string createProfileResultVal = string.Empty;
tzCampaignCxn.SetCondition(SharedSecret, xmlData, out createProfileResultVal);
txtResults.AppendText(Environment.NewLine + Environment.NewLine + createProfileResultVal);
}