class XmlWriterBackedStream 与 KB2901983 的重大变化
Breaking change in class XmlWriterBackedStream with KB2901983
我有一个针对 .NET Framework 4.0 的应用程序,昨天我们的客户进行了某种更新,我们的应用程序停止工作。在深入研究 .NET Framework 源代码后,我在 XmlWriterBackedStream class 中找到了原因。我机器上的代码如下:
// C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.ServiceModel.Web\v4.0_4.0.0.0__31bf3856ad364e35\System.ServiceModel.Web.dll
// System.ServiceModel.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
// Architecture: AnyCPU (64-bit preferred)
// Runtime: .NET 4.0
// System.ServiceModel.Channels.StreamBodyWriter.XmlWriterBackedStream
public override void Write(byte[] buffer, int offset, int count)
{
if (this.writer.WriteState == WriteState.Start)
{
this.writer.WriteStartElement("Binary", string.Empty);
this.writer.WriteBase64(buffer, offset, count);
return;
}
if (this.writer.WriteState == WriteState.Content)
{
this.writer.WriteBase64(buffer, offset, count);
}
}
而客户机器上的 .NET 4.0 Framework 代码如下所示:
// C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.ServiceModel.Web\v4.0_4.0.0.0__31bf3856ad364e35\System.ServiceModel.Web.dll
// System.ServiceModel.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
// Architecture: AnyCPU (64-bit preferred)
// Runtime: .NET 4.0
// System.ServiceModel.Channels.StreamBodyWriter.XmlWriterBackedStream
public override void Write(byte[] buffer, int offset, int count)
{
if (this.writer.WriteState == WriteState.Content || this.isQuirkedTo40Behavior)
{
this.writer.WriteBase64(buffer, offset, count);
return;
}
if (this.writer.WriteState == WriteState.Start)
{
this.writer.WriteStartElement("Binary", string.Empty);
this.writer.WriteBase64(buffer, offset, count);
}
}
注意客户机器上的 this.isQuirkedTo40Behavior
。这迫使我针对 .NET Framework 4.5 编译应用程序以使其再次运行。
这是 .NET Framework 中的错误吗?如何在不针对 4.5 框架的情况下让我的应用程序再次运行?
这是我的 class 引起的问题:
class MyMessageWriter : StreamBodyWriter
{
private readonly Action<System.IO.Stream> writerAction;
public MyMessageWriter(Action<System.IO.Stream> writer) : base(false)
{
this.writerAction = writer;
}
protected override void OnWriteBodyContents(System.IO.Stream stream)
{
this.writerAction(stream);
}
}
这似乎是安装 KB2901983(感谢 Microsoft!)带来的真正重大变化。但是我找到了解决此问题的方法,因此您仍然可以将您的应用程序定位到 .NET Framework 4.0(有点难看 - 但它有效):
class MyMessageWriter : StreamBodyWriter
{
private readonly Action<System.IO.Stream> writerAction;
public MyMessageWriter(Action<System.IO.Stream> writer) : base(false)
{
this.writerAction = writer;
}
protected override void OnWriteBodyContents(System.IO.Stream stream)
{
this.writerAction(stream);
}
protected override void OnWriteBodyContents(XmlDictionaryWriter writer)
{
writer.WriteStartElement("Binary", string.Empty);
writer.WriteBase64(new byte[0], 0, 0); // force WriteState.Content
base.OnWriteBodyContents(writer);
}
}
更新
如果您没有安装 KB2901983,此解决方案似乎不起作用。
更新 2
我不得不添加 writer.WriteBase64(new byte[0], 0, 0)
以强制 XmlDictionaryWriter 的状态为 WriteState.Content
现在它应该在安装 KB2901983 之前和之后工作
更新 3
另一种解决方案是将 XmlDictionaryWriter 包装到您自己的 Stream 派生中 class
我有一个针对 .NET Framework 4.0 的应用程序,昨天我们的客户进行了某种更新,我们的应用程序停止工作。在深入研究 .NET Framework 源代码后,我在 XmlWriterBackedStream class 中找到了原因。我机器上的代码如下:
// C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.ServiceModel.Web\v4.0_4.0.0.0__31bf3856ad364e35\System.ServiceModel.Web.dll
// System.ServiceModel.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
// Architecture: AnyCPU (64-bit preferred)
// Runtime: .NET 4.0
// System.ServiceModel.Channels.StreamBodyWriter.XmlWriterBackedStream
public override void Write(byte[] buffer, int offset, int count)
{
if (this.writer.WriteState == WriteState.Start)
{
this.writer.WriteStartElement("Binary", string.Empty);
this.writer.WriteBase64(buffer, offset, count);
return;
}
if (this.writer.WriteState == WriteState.Content)
{
this.writer.WriteBase64(buffer, offset, count);
}
}
而客户机器上的 .NET 4.0 Framework 代码如下所示:
// C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.ServiceModel.Web\v4.0_4.0.0.0__31bf3856ad364e35\System.ServiceModel.Web.dll
// System.ServiceModel.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
// Architecture: AnyCPU (64-bit preferred)
// Runtime: .NET 4.0
// System.ServiceModel.Channels.StreamBodyWriter.XmlWriterBackedStream
public override void Write(byte[] buffer, int offset, int count)
{
if (this.writer.WriteState == WriteState.Content || this.isQuirkedTo40Behavior)
{
this.writer.WriteBase64(buffer, offset, count);
return;
}
if (this.writer.WriteState == WriteState.Start)
{
this.writer.WriteStartElement("Binary", string.Empty);
this.writer.WriteBase64(buffer, offset, count);
}
}
注意客户机器上的 this.isQuirkedTo40Behavior
。这迫使我针对 .NET Framework 4.5 编译应用程序以使其再次运行。
这是 .NET Framework 中的错误吗?如何在不针对 4.5 框架的情况下让我的应用程序再次运行?
这是我的 class 引起的问题:
class MyMessageWriter : StreamBodyWriter
{
private readonly Action<System.IO.Stream> writerAction;
public MyMessageWriter(Action<System.IO.Stream> writer) : base(false)
{
this.writerAction = writer;
}
protected override void OnWriteBodyContents(System.IO.Stream stream)
{
this.writerAction(stream);
}
}
这似乎是安装 KB2901983(感谢 Microsoft!)带来的真正重大变化。但是我找到了解决此问题的方法,因此您仍然可以将您的应用程序定位到 .NET Framework 4.0(有点难看 - 但它有效):
class MyMessageWriter : StreamBodyWriter
{
private readonly Action<System.IO.Stream> writerAction;
public MyMessageWriter(Action<System.IO.Stream> writer) : base(false)
{
this.writerAction = writer;
}
protected override void OnWriteBodyContents(System.IO.Stream stream)
{
this.writerAction(stream);
}
protected override void OnWriteBodyContents(XmlDictionaryWriter writer)
{
writer.WriteStartElement("Binary", string.Empty);
writer.WriteBase64(new byte[0], 0, 0); // force WriteState.Content
base.OnWriteBodyContents(writer);
}
}
更新
如果您没有安装 KB2901983,此解决方案似乎不起作用。
更新 2
我不得不添加 writer.WriteBase64(new byte[0], 0, 0)
以强制 XmlDictionaryWriter 的状态为 WriteState.Content
现在它应该在安装 KB2901983 之前和之后工作
更新 3
另一种解决方案是将 XmlDictionaryWriter 包装到您自己的 Stream 派生中 class