(警告 - 下面的xml和无偿字符编码的unholy混合.)
简短版本:
为什么我不能得到我的服务引用调用(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>
Run Code Online (Sandbox Code Playgroud)
我设置参数,拨打电话......服务返回一条很好的消息,上面写着"没有SOU--肥皂给你!"
我在传递给webservice参数字符串中尝试了其他几种格式:
action=\"add\"
Run Code Online (Sandbox Code Playgroud)
这给了我这个电线(通过提琴手): action="add"
action="add"
Run Code Online (Sandbox Code Playgroud)
这给了我这个电报: action=&quot;add&quot;
和各种组合(action =""add""?!)与html.encode,url.encode几乎完全被轰炸,或在电线上显示为双引号.
哦,我甚至试过<![CDATA["]]周围.那也行不通.
有没有办法在soap消息的innerHtml位强制使用双引号编码?
*(因为这就是服务所需要的.不要问问题.这些不是您正在寻找的机器人)
*** 长而曲折的版本:
我正在编写一个应用程序来自动化一些目前由(winform)管理GUI应用程序处理的程序.(实际上,它是一个mmc snap in.无论如何.)
为了完成它的任务,winform应用程序通过标准的Web服务调用与它的服务器进行通信.
我正在使用VS2008的漂亮的"Web服务参考"自动生成东西(这是技术说明),并且我已成功通过Web服务进行身份验证.为了确保我正确地做事,我从GUI应用程序中捕获了调用,然后将它们与我在线上发送的内容进行了比较.一切都很好.然后我遇到了&符号的邪恶.(更恰当的说,如何正确编码)
对于其中一个调用,Web服务期望看到这样的内容:(我捕获了通过提琴手发送此应用程序的应用程序)
<?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>
Run Code Online (Sandbox Code Playgroud)
剥离所有额外的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>
Run Code Online (Sandbox Code Playgroud)
在我的代码中,我有一个像这样构建的字符串:
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>";
Run Code Online (Sandbox Code Playgroud)
当我的应用程序通过网络发送它时,fiddler捕获这个:(再次,剥离所有SOAP的东西)
<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>
Run Code Online (Sandbox Code Playgroud)
接收服务发回一个它不喜欢它的错误.它想要"d ## nit.
尖括号被正确编码,但引号在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>";
Run Code Online (Sandbox Code Playgroud)
这被发送出来(再次,通过提琴手)和我所有的&符号(在
")中转换为&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>
Run Code Online (Sandbox Code Playgroud)
而且,正如你猜测的那样,接收网络服务带回"BZZT!谢谢你玩!".
我尝试了各种类型的转义和编码序列,结果相似.实际上,我所有的操作后,经过类似HttpUtility.HtmlEncode 正确的线路上出门前,并在字符串中的任何&符号转换为:&.并且在转换中忽略引号(单引号或双引号).并且接收网络服务
希望那些被称为"狗的报价,或者它将把它带回家并回家.
我最后一个绝望的希望就是在使用IClientMessageInspector 在BeforeSendRequest事件中实现消息检查之前,正确地抓住消息(我想),并在它进入线路之前手动设置这些消息.
我捕获的信息很好.我甚至可以手动输入".
但当它被发送时,wireshark和小提琴手都向我保证它的格式很好......用引号我非常想要摆脱它.
<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>
Run Code Online (Sandbox Code Playgroud)
我的智慧结束了.我会接受任何建议,包括在[邪恶的神灵]的变化上牺牲[小可爱的东西]或者出售我的[灵魂/心灵/儿子的生物系列].相信我,它是较小的邪恶.
根据下面的请求,这里是生成的消息存根:(我认为这是你要求的......)
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;
}
Run Code Online (Sandbox Code Playgroud)
以下是它的调用方式:
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);
}
Run Code Online (Sandbox Code Playgroud)
您需要将该字符串作为 CDATA 部分放入 SOAP 消息中,以便可以完全按照您想要的格式设置它,并且 WCF 不会触及它。
您目前遇到的问题是,该服务需要介于 xml 和 html 之间的编码 - 因此 Soap 格式化程序使用的格式不能很好地处理这种编码 - 所以您总是必须自己转义引号。
不过,我有一种预感,如果您将其包含在<![CDATA[*yourstring*]]>字符串参数中的 CDATA 标记中,则该标记将通过线路转义并到达另一端,如下所示<![[*yourstring-XML-element-encoded*]]>
如果是这种情况,您可以做的是更改 VS 服务引用生成器自动生成的代码,以便代理上方法调用的参数类型接受与字符串基本相同的类型,但序列化本身作为 CDATA 部分。这种类型是基于 Marc Gravell 为回答另一个问题而编写的代码提供的。这样做的问题是,如果有人在 VS 中对该服务引用使用“更新引用”命令,则您所做的任何更改都将丢失。
因此,相反,使用 svcutil 命令行实用程序生成引用(与普遍的看法相反,VS 不使用此工具 - 遗憾的是它更灵活),手动将其生成的配置和代码导入到您的项目中,然后摆脱“服务参考”。这样,您就可以随意修改代码,并且可以轻松地在 VS 的项目树中看到它。
| 归档时间: |
|
| 查看次数: |
3595 次 |
| 最近记录: |