5

我创建了一个 BizTalk 接收位置,它有一个订阅发送端口,它接受一个封装的消息,并仅使用 XML 接收管道将其拆分为单独的消息。

<?xml version="1.0" encoding="utf-8"?>
<MyEnvelope xmlns="MyNameSpace">
    <MyData>ABC</MyData>
    <MyData>DEF</MyData>
    <MyData>GHI</MyData>
</MyEnvelope>

保存为

<?xml version="1.0" encoding="utf-8"?>
<MyData xmlns="MyNameSpace">ABC</MyData>

,

 <?xml version="1.0" encoding="utf-8"?>
 <MyData xmlns="MyNameSpace">DEF</MyData>

 <?xml version="1.0" encoding="utf-8"?>
 <MyData xmlns="MyNameSpace">GHI</MyData>

这很棒。

但是,当消息中没有元素时,服务会发送带有自闭合和空信封的消息:

<?xml version="1.0" encoding="utf-8"?>
<MyEnvelope xmlns="MyNameSpace"/>

我收到错误消息

来源:“XML 反汇编程序” 接收端口:“InLocation” URI:“c:\MyLocation*.xml” 原因:状态“processing_header”中的意外事件(“eos”)。

如果我手动创建一条不会自动关闭的消息:

<?xml version="1.0" encoding="utf-8"?>
<MyEnvelope xmlns="MyNameSpace"></MyEnvelope>

我没有错误。我的处理不受这些错误的影响,但它一定会对性能产生一些影响,并且会在 Group Hub 暂停实例视图中乱扔垃圾。

似乎 BizTalk 将自闭合节点解释为空格而不是 null。这似乎与我尝试调用没有参数的服务有关,我需要发送一个自关闭节点但 BizTalk 什么都不发送。

处理没有内容的信封一定是一个常见问题。如何配置我的应用程序以使用自闭合信封节点接收和忽略这些消息?

4

4 回答 4

3

他们似乎经常改变处理空白的行为。请参阅BizTalk 中默认空白行为的更改。我不确定您的问题是否相关,但值得一看。它没有提到 BizTalk 2013,但设置在主机中。如果您执行此配置设置,则需要专门为其设置主机,这样它就不会影响其他现有应用程序(如果有的话)。

安装以下更新之一会导致 BizTalk 更改默认行为以在映射期间保留 XML 中的空白:

  1. BizTalk 2010 CU1 或更高版本
  2. BizTalk 2009 CU3 或更高版本
  3. BizTalk 2006 R2 SP1 CU4 或更高版本
  4. 修补程序 2492255

在某些环境中,转换删除空格可能是优选的。为了恢复到这种行为,可以采取以下步骤:

在 BizTalk 2010 中,这是在主机级别设置的:

  1. 打开 BizTalk Server 管理控制台
  2. 将 BizTalk 组展开到平台设置 > 主机
  3. 右键单击主机并选择设置
  4. 选中旧版空白行为旁边的复选框
  5. 点击确定
  6. 重新启动此主机的 BizTalk 主机实例

在 BizTalk 2009 和 2006 R2 中,此值在每台计算机级别设置:

  1. 打开注册表编辑器
  2. 在基于 x86 的计算机上找到并单击以下注册表子项: • HKEY_LOCAL_MACHINE\Software\Microsoft\BizTalk Server\3.0\Administration 对于基于 x64 的计算机,单击以下注册表子项: • HKEY_LOCAL_MACHINE\Software\Microsoft\BizTalk Server \3.0\Administration
    • HKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft\BizTalk Server\3.0\Administration
  3. 右键单击并选择 DWORD 值。
  4. 键入 LegacyWhitespace 作为值名称,然后双击它并将值数据设置为 1。
  5. 退出注册表编辑器。
  6. 重新启动此计算机上的 BizTalk 主机实例
于 2014-03-31T21:29:07.850 回答
2

我没有看到或验证过这种行为,但我相信你;)。

除非您每小时获得 10K 文件或类似的东西,否则不要担心异常对性能的影响。

为了防止错误,您必须取消或重新格式化管道组件中的消息。

于 2014-03-31T17:28:29.607 回答
2

我知道这是一个老问题,但我遇到过同样的事情(特别是在返回空结果集的 SQL XML 轮询/过程中)。通常我会通过确保如果 SQL 返回一个空的结果集(优化 Data Available 语句)就不会调用它来绕过它,但有时它并不完全可能或万无一失。最后,我在解码阶段编写了一个自定义管道组件。它旨在执行以下操作:

  1. 检查这是否是一个信封模式(这个错误应该发生的唯一时间
  2. 尽量容忍 BizTalk 是格式错误的 XML(至少对于 XML 中的无效字符)
  3. 检查第一个内容元素(即根元素)是否为空
  4. 如果是这样,用“FullEndElement”重写它。
  5. 重置流并将它们添加到资源跟踪器以进行最终处理
  6. 在异常情况下,悄悄地写入调试跟踪器,但让 BizTalk 从那里获取它 - 它会做的最坏的事情是产生嘈杂但无害的错误消息。
Stream origStream = pInMsg.BodyPart.GetOriginalDataStream();
try
{
    XmlReaderSettings readerSettings = new XmlReaderSettings();
    readerSettings.CheckCharacters = false; 
    readerSettings.CloseInput = false;

    XmlReader reader = XmlReader.Create(origStream, readerSettings);
    pContext.ResourceTracker.AddResource(reader);

    reader.MoveToContent();

    IDocumentSpec docSpec = pContext.GetDocumentSpecByType(reader.NamespaceURI + "#" + reader.LocalName);
    if (!string.IsNullOrWhiteSpace(docSpec.GetBodyPath()) && reader.IsEmptyElement) // this is an envelope schema with an empty root node
    {
        XmlWriterSettings writerSettings = new XmlWriterSettings();
        writerSettings.CheckCharacters = false;
        writerSettings.OmitXmlDeclaration = true;

        MemoryStream ms = new MemoryStream(); // for such a small stream, MemoryStream is perfectly fine - normally use VirtualStream.
        pContext.ResourceTracker.AddResource(ms);

        XmlWriter writer = XmlWriter.Create(ms, writerSettings);
        pContext.ResourceTracker.AddResource(writer);

        writer.WriteStartElement(reader.Prefix, reader.LocalName, reader.NamespaceURI);
        writer.WriteFullEndElement();
        writer.Flush();

        ms.Position = 0;
        pInMsg.BodyPart.Data = ms;
    }
}
catch (Exception e)
{
    // swallow exception 
    System.Diagnostics.Debug.WriteLine(e.ToString());
}
finally // make sure we're somewhat well behaved
{
    if (pInMsg.BodyPart.Data.CanSeek == true)
        pInMsg.BodyPart.Data.Position = 0;
}
于 2016-04-12T23:39:17.437 回答
1

另一个(非常)迟到的答案。它并没有真正回答 OP 的问题,但是自从我到这里谷歌搜索错误消息并最终引导我找到这个解决方案后,我想无论如何我都会回答,以防它帮助其他人。

如果您像我一样可以控制信封的结构,您可以在信封中添加另一个级别,如果它是自动关闭的,则不会导致错误。

因此,这将导致错误:

<MyEnvelope xmlns="MyNameSpace" />

但这不会:

<MyEnvelope xmlns="MyNameSpace">
  <Body />
</MyEnvelope>

将模式的 Body XPath 设置为此嵌套级别,它应该可以正常处理。

<MyEnvelope xmlns="MyNameSpace">
    <Body>
        <MyData>ABC</MyData>
        <MyData>DEF</MyData>
        <MyData>GHI</MyData>
    </Body>
</MyEnvelope>
于 2020-08-04T17:01:10.577 回答