世界碳基金:(MTOM) 有什么方法可以更改 xop:WCF 生成的内容引用 uri 中使用的方案吗?

StackOverflow https://stackoverflow.com/questions/2280025

  •  21-09-2019
  •  | 
  •  

WCF 用途 http://tempuri/1/number 用于处理流式 MTOM 请求时的 Content-ID uri 引用。

有没有办法强制 WCF 对 xop:Include 使用不同的 Content-ID 引用?

问题背景:

我正在为支持 MTOM 的 jax ws java Web 服务构建一个 .NET 客户端,用于处理流式大数据上传。我手工制作了服务和数据联系人(WSDL 生成的合约不正确并且不允许流式传输)。

问题是 Web 服务 (jax ws) 未收到包含数据的请求正文。

它接收在标头中传输的数据。

我们已经为 ws 构建了一个 java 客户端 - 这个可以工作。

我捕获并比较了从 java 和 wcf 发出请求时的 HTTP 流量,唯一的区别在于发布多部分数据时如何生成 Content-ID 引用:

  • WCF 用途 http://tempuri/1/... 产生编码值的内容 ID 引用,例如 href="cid:http%3A%2F%2Ftempuri.org%2F1%2F634019957020047928"

  • Java 客户端使用“电子邮件样式”uri,例如 href="cid:3f3ec388-8cd9-47aa-a603-fb1bc17935b8@example.jaxws.sun.com"

这些在以下 xop-includes 中产生(数据是肥皂体中的唯一元素)(XOP 包含规范)


//WCF:
<Data>
   <xop:Include xmlns:xop="http://www.w3.org/2004/08/xop/include" href="cid:http%3A%2F%2Ftempuri.org%2F1%2F634019957020047928" />
</Data>

//JAVA:
<Data>
    <xop:Include xmlns:xop="http://www.w3.org/2004/08/xop/include" href="cid:3f3ec388-8cd9-47aa-a603-fb1bc17935b8@example.jaxws.sun.com"/>
</Data>

随后,在多部分数据中,内容由未编码的 Content-ID 引用:

--uuid:7e166bb7-042f-4ba3-b6ef-98fbbc21244b+id=1
Content-ID: <http://tempuri.org/1/634019957020047928>
Content-Transfer-Encoding: binary
Content-Type: application/octet-stream

我猜有 可能 是 jax Web 服务框架中的一个错误,它无法识别 WCF 生成的 + urlencoded Content-ID uri 引用。

有没有办法强制 WCF 对 xop:Include 使用不同的 Content-ID 引用?


编辑:我发现 XmlMtomWriter 具有GenerateUriForMimePart 方法,该方法用于生成Content-ID。

public static string GenerateUriForMimePart(int index)
{
    return string.Format(CultureInfo.InvariantCulture, 
"http://tempuri.org/{0}/{1}", new object[] { index, DateTime.Now.Ticks });
}

ID 生成似乎无论如何都不可重写。

这里描述了类似的问题,提供的答案没有帮助: http://social.msdn.microsoft.com/Forums/en/wcf/thread/f90affbd-f431-4602-a81d-cc66c049e351

有帮助吗?

解决方案

经过长时间的调查后我对自己回答:如果不重新实现整个 XmlMtomWriter 以及 WCF 中的其他相关层和关注点,这是不可能的 - 几乎 mtom 实现中涉及的所有内容都是内部的。

其他提示

我知道这是一个老问题。但两天前我也遇到了同样的问题。

我找到了一种有效的方法,但这是一个非常非常肮脏的黑客(我知道。我想过不在这里发布它,但也许它会对某人有所帮助。)希望你不会因此责怪我。

ContentId 使用 CultureInfo.InvariantCulture 进行格式化。我没有找到用自定义 CultureInfo 替换它的官方方法。但在反思的帮助下,我让它运行起来。以下实现仅适用于.Net 4.0。

public class NoTempUriInvariantCultureInfo : CultureInfo, ICustomFormatter
{
   private static CultureInfo originalCulture;
   private static object originalCultureLock;
   private static int enableCounter;

   private NoTempUriInvariantCultureInfo(CultureInfo invariantCulture)
      : base(invariantCulture.Name)
   {
      originalCulture = invariantCulture;
   }

   public static void Enable()
   {
      if(originalCultureLock == null)
         originalCultureLock = new object();

      lock (originalCultureLock)
      {
         if (enableCounter == 0)
         {
            var mInvCultField = typeof (CultureInfo).GetField("s_InvariantCultureInfo", BindingFlags.NonPublic | BindingFlags.Static);
            mInvCultField.SetValue(null, new NoTempUriInvariantCultureInfo(CultureInfo.InvariantCulture));
         }
         enableCounter++;
      }
   }

   public static void Disable()
   {
      lock (originalCulture)
      {
         if (enableCounter == 0)
            return;

         enableCounter--;
         if (enableCounter == 0)
         {
            var mInvCultField = typeof (CultureInfo).GetField("s_InvariantCultureInfo", BindingFlags.NonPublic | BindingFlags.Static);
            mInvCultField.SetValue(null, NoTempUriInvariantCultureInfo.originalCulture);
         }
      }
   }

   public override object GetFormat(Type formatType)
   {
      var result = originalCulture.GetFormat(formatType);
      return result ?? this;
   }

   public string Format(string format, object arg, IFormatProvider formatProvider)
   {
      if (format == null)
         return System.Text.RegularExpressions.Regex.Replace(arg.ToString().Replace("http%3A%2F%2Ftempuri.org%2F1%2F", ""), "http[:][/][/]tempuri[.]org[/][0-9]+[/]*", "");
      return String.Format("{0:" + format + "}", arg);
   }
}

我仅在 WCF 调用之前启用我自己的“InvariantCulture”。

NoTempUriInvariantCultureInfo.Enable();
try
{
    // make your call
}
finally
{
    NoTempUriInvariantCultureInfo.Disable();
}

CultureInfo.InvariantCulture 是一个全局状态对象。启用我自己的 InvariantCulture 会影响所有其他线程。再说一遍,这是一个肮脏的黑客行为。但它有效。

这两个 XOP 都包含您指出的示例,这些示例是正确的并且根据 W3C 可以接受。我将它们分别称为 URL 格式和电子邮件格式。

我不是 JAVA 开发人员,但记得在与特定 JAVA Web 服务交互时遇到过类似的问题。我记得在某个特定的 JAVA 版本中存在一个错误,在他们(JAVA 开发人员)升级到下一个版本后,这个问题就消失了。我希望能为您提供更多详细信息,但当时,有足够多的问题需要我从电话那头解决,我很高兴缺陷日志上少了一项。

//WCF: using URL format
<Data>
   <xop:Include xmlns:xop="http://www.w3.org/2004/08/xop/include" href="cid:http%3A%2F%2Ftempuri.org%2F1%2F634019957020047928" />
</Data>

//JAVA: using EMAIL format
<Data>
    <xop:Include xmlns:xop="http://www.w3.org/2004/08/xop/include" href="cid:3f3ec388-8cd9-47aa-a603-fb1bc17935b8@example.jaxws.sun.com"/>
</Data>
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top