<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:pingback="http://madskills.com/public/xml/rss/module/pingback/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" version="2.0">
  <channel>
    <title>Matevž Gačnik's Weblog - .NET 3.5 - General</title>
    <link>https://www.request-response.com/blog/</link>
    <description>Technology Philanthropy</description>
    <image>
      <url>http://www.request-response.com/blog/images/favicon.jpg</url>
      <title>Matevž Gačnik's Weblog - .NET 3.5 - General</title>
      <link>https://www.request-response.com/blog/</link>
    </image>
    <language>en-us</language>
    <copyright>Matevz Gacnik</copyright>
    <lastBuildDate>Mon, 06 Apr 2009 12:22:33 GMT</lastBuildDate>
    <generator>newtelligence dasBlog 2.1.8102.813</generator>
    <managingEditor>matevz.gacnik@gmail.com</managingEditor>
    <webMaster>matevz.gacnik@gmail.com</webMaster>
    <item>
      <trackback:ping>https://www.request-response.com/blog/Trackback.aspx?guid=d27d4672-92f5-4944-8fc9-1f7f098d36e9</trackback:ping>
      <pingback:server>https://www.request-response.com/blog/pingback.aspx</pingback:server>
      <pingback:target>https://www.request-response.com/blog/PermaLink,guid,d27d4672-92f5-4944-8fc9-1f7f098d36e9.aspx</pingback:target>
      <dc:creator>Matevz Gacnik</dc:creator>
      <wfw:comment>https://www.request-response.com/blog/CommentView,guid,d27d4672-92f5-4944-8fc9-1f7f098d36e9.aspx</wfw:comment>
      <wfw:commentRss>https://www.request-response.com/blog/SyndicationService.asmx/GetEntryCommentsRss?guid=d27d4672-92f5-4944-8fc9-1f7f098d36e9</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <font face="Courier New">XmlSerializer</font> is a great peace of technology. Combined
with <font face="Courier New">xsd.exe</font> and friends (<font face="Courier New">XmlSerializerNamespaces</font>,
et al.) it's a powerful tool for one to get around XML instance serialization/deserialization.
</p>
        <p>
But, there is a potentially serious bug present, even in 3.5 SP1 version of the .NET
Framework.
</p>
        <p>
Suppose we have the following XML structure:
</p>
        <p>
          <font face="Courier New">&lt;Envelope xmlns="NamespaceA" 
<br />
          xmlns:B="NamespaceB"&gt;<br />
  &lt;B:Header&gt;&lt;/B:Header&gt;<br />
  &lt;Body&gt;&lt;/Body&gt;<br />
&lt;/Envelope&gt;</font>
        </p>
        <p>
This tells you that <font face="Courier New">Envelope</font>, and <font face="Courier New">Body</font> elements
are in the same namespace (namely <font face="Courier New">'NamespaceA'</font>), while <font face="Courier New">Header</font> is
qualified with <font face="Courier New">'NamespaceB'</font>.
</p>
        <p>
Now suppose we need to programmatically insert <font face="Courier New">&lt;B:Header&gt;</font> element
into an empty, <em>core</em>, document.
</p>
        <p>
Core document:
</p>
        <p>
          <font face="Courier New">&lt;Envelope xmlns="NamespaceA" 
<br />
          xmlns:B="NamespaceB"&gt;<br />
  &lt;Body&gt;&lt;/Body&gt;<br />
&lt;/Envelope&gt;</font>
        </p>
        <p>
Now do an <font face="Courier New">XmlNode.InsertNode()</font> of the following:
</p>
        <p>
          <font face="Courier New">&lt;B:Header&gt;...&lt;/B:Header&gt;</font>
        </p>
        <p>
We should get:
</p>
        <p>
          <font face="Courier New">&lt;Envelope xmlns="NamespaceA" 
<br />
          xmlns:B="NamespaceB"&gt;<br />
  &lt;B:Header&gt;...&lt;/B:Header&gt;<br />
  &lt;Body&gt;&lt;/Body&gt;<br />
&lt;/Envelope&gt;</font>
        </p>
        <p>
To get the <em>to be inserted part</em> one would serialize (using <font face="Courier New">XmlSerializer</font>)
the following <font face="Courier New">Header</font> document:
</p>
        <p>
          <font face="Courier New">&lt;B: Header xmlns:B="NamespaceB"&gt;<br />
  ...<br />
&lt;/B:Header&gt;</font>
        </p>
        <p>
To do this, a simple <font face="Courier New">XmlSerializer</font> magic will do the
trick:
</p>
        <p>
          <font face="Courier New">XmlSerializerNamespaces xsn = new XmlSerializerNamespaces();<br />
xsn.Add("B", "NamespaceB");</font>
        </p>
        <p>
          <font face="Courier New">XmlSerializer xSer = new XmlSerializer(typeof(Header));<br />
XmlTextWriter tw = new XmlTextWriter(ms, null);<br />
xSer.Serialize(tw, h, xsn);</font>
        </p>
        <p>
          <font face="Courier New">ms.Seek(0, SeekOrigin.Begin);</font>
        </p>
        <p>
          <font face="Courier New">XmlDocument doc = new XmlDocument()<br />
doc.Load(ms);<br />
ms.Close();</font>
        </p>
        <p>
This would generate exactly what we wanted. A prefixed namespace based XML document,
with the <font face="Courier New">B</font> prefix bound to <font face="Courier New">'NamespaceB'</font>.
</p>
        <p>
Now, if we would import this document fragment into our core document using <font face="Courier New">XmlNode.ImportNode()</font>,
we would get:
</p>
        <p>
          <font face="Courier New">&lt;Envelope xmlns="NamespaceA" 
<br />
          xmlns:B="NamespaceB"&gt;<br />
  &lt;B:Header <font color="#ff0000">xmlns:B="NamespaceB"</font>&gt;...&lt;/B:Header&gt;<br />
  &lt;Body&gt;&lt;/Body&gt;<br />
&lt;/Envelope&gt;</font>
        </p>
        <p>
Which is valid and actually, from an XML Infoset view, an <em>isomorphic</em> document
to the original. So what if it's got the same namespace declared twice, right?
</p>
        <p>
Right - until you involve digital signatures. I have described a specific problem
with ambient namespaces in length in this blog entry: <a href="http://www.request-response.com/blog/PermaLink,guid,26149053-63bc-495e-bab0-8d14e7e46190.aspx">XmlSerializer,
Ambient XML Namespaces and Digital Signatures</a>.
</p>
        <p>
When importing a node from another context, <font face="Courier New">XmlNode</font> and
friends do a resolve against all namespace declarations in scope. So, when importing
such a header, <strong>we shouldn't get</strong> a duplicate namespace declaration.
</p>
        <p>
The problem is, we don't get a duplicate namespace declaration, since <font face="Courier New">XmlSerializer</font> actually
inserts a normal XML attribute into the <font face="Courier New">Header</font> element.
That's why we <strong>seem to get</strong> another namespace declaration. It's actually
not a declaration but a plain old attribute. It's even visible (in this
case in <font face="Courier New">XmlElement.Attributes</font>), and it definitely
shouldn't be there.
</p>
        <p>
So if you hit this special case, remove all attributes before importing the node into
your core document. Like this:
</p>
        <p>
          <font face="Courier New">XmlSerializerNamespaces xsn = new XmlSerializerNamespaces();<br />
xsn.Add("B", "NamespaceB");</font>
        </p>
        <p>
          <font face="Courier New">XmlSerializer xSer = new XmlSerializer(typeof(Header));<br />
XmlTextWriter tw = new XmlTextWriter(ms, null);<br />
xSer.Serialize(tw, h, xsn);</font>
        </p>
        <p>
          <font face="Courier New">ms.Seek(0, SeekOrigin.Begin);</font>
        </p>
        <p>
          <font face="Courier New">XmlDocument doc = new XmlDocument()<br />
doc.Load(ms);<br />
ms.Close();<br /><font color="#ff0000">doc.DocumentElement.Attributes.RemoveAll();</font></font>
        </p>
        <p>
Note that the <strong>serialized document representation will not change</strong>,
since an ambient namespace declaration (B linked to 'NamespaceB') still exists in
the XML Infoset of <font face="Courier New">doc</font> XML document.<br /></p>
        <img width="0" height="0" src="https://www.request-response.com/blog/aggbug.ashx?id=d27d4672-92f5-4944-8fc9-1f7f098d36e9" />
      </body>
      <title>Bug in XmlSerializer, XmlSerializerNamespaces</title>
      <guid isPermaLink="false">https://www.request-response.com/blog/PermaLink,guid,d27d4672-92f5-4944-8fc9-1f7f098d36e9.aspx</guid>
      <link>https://www.request-response.com/blog/PermaLink,guid,d27d4672-92f5-4944-8fc9-1f7f098d36e9.aspx</link>
      <pubDate>Mon, 06 Apr 2009 12:22:33 GMT</pubDate>
      <description>&lt;p&gt;
&lt;font face="Courier New"&gt;XmlSerializer&lt;/font&gt; is a great peace of technology. Combined
with &lt;font face="Courier New"&gt;xsd.exe&lt;/font&gt; and friends (&lt;font face="Courier New"&gt;XmlSerializerNamespaces&lt;/font&gt;,
et al.) it's a powerful tool for one to get around XML instance serialization/deserialization.
&lt;/p&gt;
&lt;p&gt;
But, there is a potentially serious bug present, even in 3.5 SP1 version of the .NET
Framework.
&lt;/p&gt;
&lt;p&gt;
Suppose we have the following XML structure:
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;&amp;lt;Envelope xmlns="NamespaceA" 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; xmlns:B="NamespaceB"&amp;gt;&lt;br&gt;
&amp;nbsp; &amp;lt;B:Header&amp;gt;&amp;lt;/B:Header&amp;gt;&lt;br&gt;
&amp;nbsp; &amp;lt;Body&amp;gt;&amp;lt;/Body&amp;gt;&lt;br&gt;
&amp;lt;/Envelope&amp;gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
This tells you that &lt;font face="Courier New"&gt;Envelope&lt;/font&gt;, and &lt;font face="Courier New"&gt;Body&lt;/font&gt; elements
are in the same namespace (namely &lt;font face="Courier New"&gt;'NamespaceA'&lt;/font&gt;), while &lt;font face="Courier New"&gt;Header&lt;/font&gt; is
qualified with &lt;font face="Courier New"&gt;'NamespaceB'&lt;/font&gt;.
&lt;/p&gt;
&lt;p&gt;
Now suppose we need to programmatically insert &lt;font face="Courier New"&gt;&amp;lt;B:Header&amp;gt;&lt;/font&gt; element
into an empty, &lt;em&gt;core&lt;/em&gt;, document.
&lt;/p&gt;
&lt;p&gt;
Core document:
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;&amp;lt;Envelope xmlns="NamespaceA" 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; xmlns:B="NamespaceB"&amp;gt;&lt;br&gt;
&amp;nbsp; &amp;lt;Body&amp;gt;&amp;lt;/Body&amp;gt;&lt;br&gt;
&amp;lt;/Envelope&amp;gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
Now do an &lt;font face="Courier New"&gt;XmlNode.InsertNode()&lt;/font&gt; of the following:
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;&amp;lt;B:Header&amp;gt;...&amp;lt;/B:Header&amp;gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
We should get:
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;&amp;lt;Envelope xmlns="NamespaceA" 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; xmlns:B="NamespaceB"&amp;gt;&lt;br&gt;
&amp;nbsp; &amp;lt;B:Header&amp;gt;...&amp;lt;/B:Header&amp;gt;&lt;br&gt;
&amp;nbsp; &amp;lt;Body&amp;gt;&amp;lt;/Body&amp;gt;&lt;br&gt;
&amp;lt;/Envelope&amp;gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
To get the &lt;em&gt;to be inserted part&lt;/em&gt; one would serialize (using &lt;font face="Courier New"&gt;XmlSerializer&lt;/font&gt;)
the following &lt;font face="Courier New"&gt;Header&lt;/font&gt; document:
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;&amp;lt;B: Header xmlns:B="NamespaceB"&amp;gt;&lt;br&gt;
&amp;nbsp; ...&lt;br&gt;
&amp;lt;/B:Header&amp;gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
To do this, a simple &lt;font face="Courier New"&gt;XmlSerializer&lt;/font&gt; magic will do the
trick:
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;XmlSerializerNamespaces xsn = new XmlSerializerNamespaces();&lt;br&gt;
xsn.Add("B", "NamespaceB");&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;XmlSerializer xSer = new XmlSerializer(typeof(Header));&lt;br&gt;
XmlTextWriter tw = new XmlTextWriter(ms, null);&lt;br&gt;
xSer.Serialize(tw, h, xsn);&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;ms.Seek(0, SeekOrigin.Begin);&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;XmlDocument doc = new XmlDocument()&lt;br&gt;
doc.Load(ms);&lt;br&gt;
ms.Close();&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
This would generate exactly what we wanted. A prefixed namespace&amp;nbsp;based XML document,
with the &lt;font face="Courier New"&gt;B&lt;/font&gt; prefix bound to &lt;font face="Courier New"&gt;'NamespaceB'&lt;/font&gt;.
&lt;/p&gt;
&lt;p&gt;
Now, if we would import this document fragment into our core document using &lt;font face="Courier New"&gt;XmlNode.ImportNode()&lt;/font&gt;,
we would get:
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;&amp;lt;Envelope xmlns="NamespaceA" 
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; xmlns:B="NamespaceB"&amp;gt;&lt;br&gt;
&amp;nbsp; &amp;lt;B:Header &lt;font color=#ff0000&gt;xmlns:B="NamespaceB"&lt;/font&gt;&amp;gt;...&amp;lt;/B:Header&amp;gt;&lt;br&gt;
&amp;nbsp; &amp;lt;Body&amp;gt;&amp;lt;/Body&amp;gt;&lt;br&gt;
&amp;lt;/Envelope&amp;gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
Which is valid and actually, from an XML Infoset view, an &lt;em&gt;isomorphic&lt;/em&gt; document
to the original. So what if it's got the same namespace declared twice, right?
&lt;/p&gt;
&lt;p&gt;
Right - until you involve digital signatures. I have described a specific problem
with ambient namespaces in length in this blog entry: &lt;a href="http://www.request-response.com/blog/PermaLink,guid,26149053-63bc-495e-bab0-8d14e7e46190.aspx"&gt;XmlSerializer,
Ambient XML Namespaces and Digital Signatures&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
When importing a node from another context, &lt;font face="Courier New"&gt;XmlNode&lt;/font&gt; and
friends do a resolve against all namespace declarations in scope. So, when importing
such a header, &lt;strong&gt;we shouldn't get&lt;/strong&gt; a duplicate namespace declaration.
&lt;/p&gt;
&lt;p&gt;
The problem is, we don't get a duplicate namespace declaration, since &lt;font face="Courier New"&gt;XmlSerializer&lt;/font&gt; actually
inserts a normal&amp;nbsp;XML attribute into the &lt;font face="Courier New"&gt;Header&lt;/font&gt; element.
That's why we &lt;strong&gt;seem to get&lt;/strong&gt; another namespace declaration. It's actually
not a declaration but a&amp;nbsp;plain old&amp;nbsp;attribute. It's even visible (in this
case&amp;nbsp;in &lt;font face="Courier New"&gt;XmlElement.Attributes&lt;/font&gt;), and it definitely
shouldn't be there.
&lt;/p&gt;
&lt;p&gt;
So if you hit this special case, remove all attributes before importing the node into
your core document. Like this:
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;XmlSerializerNamespaces xsn = new XmlSerializerNamespaces();&lt;br&gt;
xsn.Add("B", "NamespaceB");&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;XmlSerializer xSer = new XmlSerializer(typeof(Header));&lt;br&gt;
XmlTextWriter tw = new XmlTextWriter(ms, null);&lt;br&gt;
xSer.Serialize(tw, h, xsn);&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;ms.Seek(0, SeekOrigin.Begin);&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font face="Courier New"&gt;XmlDocument doc = new XmlDocument()&lt;br&gt;
doc.Load(ms);&lt;br&gt;
ms.Close();&lt;br&gt;
&lt;font color=#ff0000&gt;doc.DocumentElement.Attributes.RemoveAll();&lt;/font&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
Note that the &lt;strong&gt;serialized document representation will not change&lt;/strong&gt;,
since an ambient namespace declaration (B linked to 'NamespaceB') still exists in
the XML Infoset of &lt;font face="Courier New"&gt;doc&lt;/font&gt; XML document.&lt;br&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="https://www.request-response.com/blog/aggbug.ashx?id=d27d4672-92f5-4944-8fc9-1f7f098d36e9" /&gt;</description>
      <comments>https://www.request-response.com/blog/CommentView,guid,d27d4672-92f5-4944-8fc9-1f7f098d36e9.aspx</comments>
      <category>.NET 3.5 - General</category>
      <category>XML</category>
    </item>
  </channel>
</rss>