【问题标题】:Inserting Values from an Array into a SOAP Message based on Key基于键将数组中的值插入到 SOAP 消息中
【发布时间】:2017-10-19 14:47:49
【问题描述】:

在一个 ASP.NET 应用程序中,用户(“用户 A”)可以使用 SOAP 设置他们自己的 Web 服务连接,我让他们插入自己的信封,例如,可能是这样的:

//Formatted for Clarity
string soapMessage = 
"<soap: Envelope //StandardStuff>
  <soap:Header //StandardStuff>
    <wsse:UsernameToken>
      <wsse: Username>{F1}</wsse:Username>
      <wsse: Password Type''>{F2}</wsse:Password>  
    </wsse:UsernameToken>
  </soap:Header>
  <soap:Body>
    <ref:GetStuff>
      <ref:IsActive>{F3}</ref:IsActive>
    </ref:GetStuff>
  </soap:Body>
</soap:Envelope>"

同时,我是一个“用户 B”,它发送一个数据数组,从 Javascript 作为 json 传递下来,看起来有点像这样:

[
  { 
    key: "F1", 
    value: "A" 
  },
  { 
    key: "F2", 
    value: "B" 
  },
  { 
    key: "F3", 
    value: "C" 
  }
];

此数组在反序列化之前作为字符串进入竞争 (dynamic JsonObject = JsonConvert.DeserializeObject(stringifiedJson);)。

现在,我希望能够将相应的值插入信封,最好具有一定程度的安全性,不允许人们通过在数组中插入奇怪的值来做时髦的事情(正则表达式可能是我的最后的手段)。

到目前为止,我知道像这样构建字符串的概念(肥皂消息中的 {}{0}, {1} &amp; {2} 替换):

string value1 = "A";
string value2 = "B";
string value3 = "C";
var body = string.Format(@soapMessage, value1, value2, value3);

request.ContentType = "application/soap+xml; charset=utf-8";
request.ContentLength = body.Length;
request.Accept = "text/xml";
request.GetRequestStream().Write(Encoding.UTF8.GetBytes(body), 0, body.Length);

但是这个数组中的值的数量以及可能会根据用户的输入以及引用顺序的变化而变化,所以我需要一些更灵活的东西。我对进行 SOAP 调用非常陌生,所以尽可能愚蠢的答案将不胜感激。

【问题讨论】:

标签: javascript c# asp.net web-services soap


【解决方案1】:

考虑创建一个函数,将占位符替换为其各自的值。

private string FormatMessage(string soapMessage, IDictionary<string, string> parameters) {
    var message = soapMessage;
    foreach (var kvp in parameters) {
        var placeholder = "{" + kvp.Key + "}";
        if (message.IndexOf(placeholder) > -1) {
            message = message.Replace(placeholder, kvp.Value);
        }
    }
    return message;
}

字典是从提供给函数的 JSON 中提取的。

var parameters = JsonConvert.DeserializeObject<IDictionary<string, string>>(json);

string body = FormatMessage(soapMessage, parameters);

但是,您需要验证提供的值和键以避免可能对您的系统产生不利影响的注入。

【讨论】:

  • 您对如何验证这些值有什么建议吗?问题在于,这涉及一个用户向另一个用户提供要填写的消息,因此没有关于此消息或值可能包含什么的先验知识。
  • @Patrick,这些是您在转换消息之前需要处理的实现问题。鉴于您是代码的控制者,您始终可以在尝试转换消息之前验证提供的值是否与当前用户匹配。
【解决方案2】:

使用 xml 处理器而不是字符串替换来处理 xml 总是一个好主意。 我的交叉想法可能不完全适合您的用例,我必须承认,我没有 100% 了解您的大局。

无论如何,我的回答是您可以使用 xpaths 作为密钥,这将使您能够在后端使用 xml 处理工具。此时您不必验证任何内容,这在很大程度上取决于架构。

所以在我看来,javascript 提供了这种结构:

[
  { 
    key: "//family-name", 
    value: "Michael" 
  },
  { 
    key: "//nickname", 
    value: "Jackson" 
  }
];

还有后端:

XmlElement foo = (XmlElement)doc.SelectSingleNode(key);
foo.InnerText = value;

【讨论】:

  • 这个想法是肥皂消息由用户 A 提供,值由用户 B 提供,因此让用户 A 在 xml 选择器中思考可能很复杂,但我绝对喜欢你开箱即用的想法。
【解决方案3】:

恕我直言,这项工作的最佳工具是 XSLT:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:crs="CRS610MI" exclude-result-prefixes="crs">
<xsl:output method="xml"/>
<xsl:template match="/">
  <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
    <soap:Body>
    <xsl:apply-templates select="node()|@*"/>
    </soap:Body>
  </soap:Envelope>
</xsl:template>
<xsl:template match="node()|@*">
    <xsl:copy>
        <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>
</xsl:template>
</xsl:stylesheet>

关于这个特定主题有一篇关于 SO 的帖子:

Wrap XML in SOAP envelope in .net

.NET 支持开箱即用的 XSLT,因此您不需要第三方库。我会将 JSON 加载到 XML 对象中,并将其应用于 XSLT 模板,您将对其进行修改以尊重您在内存中的 XML 结构。

在 C# 中使用 XmlLoader 将 JSON 加载到 XML 对象中:

XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
string jsonText = JsonConvert.SerializeXmlNode(doc);

// To convert JSON text contained in string json into an XML node
XmlDocument doc = JsonConvert.DeserializeXmlNode(json);

在 .NET 中加载 XSLT 模板非常简单:

var xml = XDocument.Load(JsonReaderWriterFactory.CreateJsonReader(
Encoding.ASCII.GetBytes(jsonString), new XmlDictionaryReaderQuotas()));

这是一种干净而专业的方法,我认为符合您的标准。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-10-25
    • 1970-01-01
    • 2013-06-02
    • 2011-11-16
    • 1970-01-01
    • 2021-03-03
    • 2013-04-06
    • 1970-01-01
    相关资源
    最近更新 更多