Thoughts from Dan Miser RSS 2.0
# Tuesday, 29 January 2008

I have a .NET application that generates an XML file via serialization (through XmlTextWriter) and submits the data via https. Recently, they changed something on their end to only accept an upper cased UTF-8 encoding, like this:


<?xml version="1.0" encoding="UTF-8"?>

Unfortunately, using the .NET classes mentioned above, it generates the encoding string in lower case. I could find one mention of this on google, and they said to have the other company change (not an option here), or override XmlTextWriter. I went with that approach, making heavy use of Reflector along the way. I started by looking at the WriteStartDocument method, but realized that the private StartDocument is the thing that generates the output. It also gets called by the overloaded WriteStartDocument, so I'd need to override that method, too. However, in the private StartDocument method, it uses a bunch of private variables and generates output via another private method, InternalWriteProcessingInstructions. Ugly. At this point I realize that XmlTextWriter is not a class made for inheriting.

Back to Reflector, and I notice that the Encoding.WebName is the property used to write out the encoding string. I now create a descendant class of UTF8Encoding. The class is listed below. Now I just call XmlTextWriter, passing in UpperCaseUTF8Encoding.UpperCaseUTF8 for the Encoding type, and everything works perfectly.

    public class UpperCaseUTF8Encoding : UTF8Encoding
    {
        public override string WebName
        {
            get { return base.WebName.ToUpper(); }
        }

        public static UpperCaseUTF8Encoding UpperCaseUTF8
        {
            get
            {
                if (upperCaseUtf8Encoding == null)
                    upperCaseUtf8Encoding = new UpperCaseUTF8Encoding();
                return upperCaseUtf8Encoding;
            }
        }

        private static UpperCaseUTF8Encoding upperCaseUtf8Encoding = null;
    }
# Sunday, 30 December 2007

I have been reading Dustin Campbell's series, The 12 Days of Refactor! X-mas, with interest. He's a very good writer, and has broken down a bunch of Developer Express features into easy to digest chunks of information.

The episode I linked to above touched on the XML Literal support that shipped with VB in Visual Studio 2008. The one sentence summary of this technology is that it lets the VB compiler translate raw XML in the source code into strongly-typed code using XML classes under the hood. It's a very nice idea, and I encourage you to look at the links to learn a little more about it.

While the VB team thought this was a good idea and added the feature, Anders and the C# team believed that it was superfluous to add such a thing to the C# side. I haven't really made up my mind which group I side with yet. However, Anders is benevolent :-), so he gave us the little-documented PasteXmlAsLinq addin that will take XML on the clipboard and paste it into a file in C# syntax building the XML up using classes like XElement.

In a default install of VS2008, open C:\Program Files\Microsoft Visual Studio 9.0\Samples\1033\CSharpSamples.zip and extract the LinqSamples\PasteXmlAsLinq files. There is a Readme.html file in there that tells you how to build, install and use the addin.

While this isn't the same as VB's support for XML Literals, it does make things easier to work with.

Sunday, 30 December 2007 23:02:25 (GMT Standard Time, UTC+00:00)  #    Comments [1] -
.NET | LINQ | XML
# Thursday, 08 March 2007
I read Scott Hanselman's well-written article HOW TO: Debug into a .NET XmlSerializer Generated Assembly. I can add a few more little (and most likely obvious) things to his article:
  • This still works in .NET 2.0.
  • If you just do an Add New Item to add a new Application Configuration File to your project in VS, you can just paste the debugging flags in, and the config file will get deployed to the application directory automatically.
  • You can just Step Into (F11) the call to x.Serialize, and you will be taken into the proper generated file. You may want to open the file manually as Scott mentioned, but I find it to be faster to press F11, and then go to the place in the file I want to debug.

In the end, we ended up writing our own serialization for .NET CF due to one too many bugs.

Thursday, 08 March 2007 20:26:21 (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET | XML
# Wednesday, 10 January 2007
XML serialization is handy, but it does lack some power. For example, if you have class inheritance, and you want a property of the child class to have a different name than the one given to it by the parent, you will get an error at run-time when trying to serialize the object: "Member 'Derived.Name' hides inherited member 'Base.Name', but has different custom attributes.".

Assume you have a class structure like this:

public abstract class Base

{

    private int id;

    private string name;

 

    [XmlElement("id")]

    public int Id

    {

        get { return id; }

        set { id = value; }

    }

 

    [XmlElement("name")]

    public virtual string Name

    {

        get { return name; }

        set { name = value; }

    }

}

 

public class Derived : Base

{

    [XmlElement("newName")]

    public override string Name

    {

        get { return base.Name; }

        set { base.Name = value; }

    }

}

To see the error, call it like this:

static void Main(string[] args)

{

    Derived d = new Derived();

    d.Id = 23;

    d.Name = "Dan";

    string xml = GetXMLFromObject(d);

    Console.WriteLine(xml);

}

Download the sample application here to play with it.

Wednesday, 10 January 2007 17:57:12 (GMT Standard Time, UTC+00:00)  #    Comments [1] -
.NET | XML
# Tuesday, 09 January 2007
Some times, it is better to have a minimal format for your XML file. When using XmlSerializer, it likes to add the standard XML namespaces to the generated XML file. If you want those gone, use code like this:

public static string GetXMLFromObject(object obj)

{

    XmlSerializer xs = new XmlSerializer(obj.GetType());

 

    // Set up chain of writers

    StringBuilder sb = new StringBuilder();

    using (XmlTextWriter writer = new XmlTextWriter(new StringWriter(sb)))

    {

        writer.Formatting = Formatting.Indented;

 

        // Remove standard namespace attributes

        XmlSerializerNamespaces xsn = new XmlSerializerNamespaces();

        xsn.Add(string.Empty, string.Empty);

        xs.Serialize(writer, obj, xsn);

    }

 

    return sb.ToString();

}

The key is to create an XmlSerializerNameSpaces object, populate it with empty strings, and then pass it to the XmlSerizliazer. The result is a more compact XML file. Note that this works, despite the comment in the documentation explicitly saying that it isn't supported.

You can also use this class to add your own custom namespaces. This could be useful to prefix certain elements with a certain namespace.

Tuesday, 09 January 2007 15:52:45 (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET | XML
# Monday, 08 January 2007
While the XmlIgnore/Specified pattern to control serialization is very useful, it could be overkill for simpler serialization scenarios.

When you create an object with a bool field, that field is initialized and defaulted to the value of false. Under normal conditions, this value will get serialized every time. However, what if we only care about capturing that value when the value is true? It turns out that we can use DefaultValueAttribute. The first thing that may stand out to you is that this attribute lives in the System.ComponentModel namespace, and not in an XML namespace. The online help also mentions that this is used for visual designers and code generators. XmlSerializer also uses this attribute to decide whether or not to stream the value during serialization, since it's really a form of a code generator (more on that in a later post). If the value of the field or property matches the value that you specify in the DefaultValueAttribute, then that property will not be streamed.

Using an XmlAttributeAttribute, you can specify that a certain property will be expressed as an XML attribute instead of an XML element. To demonstrate both of these concepts, see the following code:

public class Url

{

    [XmlAttribute("address")]

    public string Address;

    [XmlAttribute("primary"), DefaultValue(false)]

    public bool Primary;

    public Url()

    {

   }

}

static void Main(string[] args)

{

    Url u = new Url();

    u.Address = "http://testing/";

    string xml = GetXMLFromObject(u);

    Console.WriteLine(xml);

}

This produces roughly the following output (XML namespace information is stripped here. I will show how to do this in code with a future post). Notice that the Primary attribute is not generated because it matches the DefaultValue.

<?xml version="1.0" encoding="utf-16"?>

<Url address="http://testing/" />

Monday, 08 January 2007 15:09:43 (GMT Standard Time, UTC+00:00)  #    Comments [0] -
.NET | XML
# Friday, 05 January 2007
David Hervieux posted a link to some Serialization FAQs in a comment to my last post. This material is good, and actually forced me to go back through what I wanted to cover, since I didn't want to just add posts that duplicate what can be found easily on the web. I'll still move forward with a few items in XML serialization that I think are unique.

The XMLIgnore attribute is used to tell the XmlSerializer that this field is transient, and should not be (de)serialized. The most typical use for this would be to mark calculated fields with this attribute. This is an easy customization that helps your serialization process, but it leaves a bit to be desired. It's an "all or nothing" approach, where the property is either streamed or not.

This MSDN article hints at what to do to get more fine-grained control of this aspect of serialization. Basically, you create a public boolean field or property named propertyNameSpecified for the property you want to control. The XmlSerializer uses this convention to determine whether or not to include the associated property for serialization. Since this new Specified field will be eligible for serialization, be sure to mark it with the XmlIgnore attribute to prevent it from being serialized.

A very simple code listing showing how this all fits together:

    public class Player

    {

        private int number;

        private string name;

        [XmlElement("jerseyNumber")]

        public int Number

        {

            get { return number; }

            // You could add more logic here to only set NumberSpecified based on some criteria

            set { number = value; NumberSpecified = true; }

        }

        [XmlElement("playerName")]

        public string Name

        {

            get { return name; }

            set { name = value; }

        }

        [XmlIgnore]

        public bool NumberSpecified;

    }

The downsides to using this techniques are:
  • It requires another field, and some custom logic to make this work.
  • It requires that the Specified field be marked as public, exposing it to consumers of the library. There is no real reason why the XmlSerializer couldn't use reflection to get at a non-public member.
  • If you use a property, it must be a full read-write property. A read-only property could very well suffice here, and make your code easier to maintain.

      Download the very simple sample showing this behavior here.

    • Friday, 05 January 2007 19:37:20 (GMT Standard Time, UTC+00:00)  #    Comments [2] -
      .NET | XML
      # Wednesday, 27 December 2006
      Serializing between .NET objects and XML files, and vice versa, is extremely easy, yet flexible and powerful. I'll be blogging a few entries about this topic in the days to come. This entry will set the stage, showing the basics of XML serialization.

      Assume you have a (stripped down) class definition like this:

          public class Player

          {

              [XmlElement("jerseyNumber")]

              public int Number { get; set; }

              [XmlElement("playerName")]

              public string Name { get; set; }

          }

      And you wanted to read/write an XML file that looked like this:

      <Player>

        <jerseyNumber>23</jerseyNumber>

        <playerName>Dan</playerName>

      </Player>

      The key to making this happen is the XmlSerializer class. This is the class that will convert between public properties and XML elements. You can also decorate your class with simple attributes to coerce your class into generating custom XML (i.e. XML attributes, hide or rename elements, etc.).

      Here are a couple of helper methods, and a sample that uses them to show you how all of this comes together.

              static string GetXMLFromObject(object obj)

              {

                  XmlSerializer ser = new XmlSerializer(obj.GetType());

       

                  StringBuilder sb = new StringBuilder();

                  using (XmlTextWriter writer = new XmlTextWriter(new StringWriter(sb)))

                  {

                      writer.Formatting = Formatting.Indented;

                      ser.Serialize(writer, obj);

                      return sb.ToString();

                  }

              }

       

              static object CreateObjectFromXML(string xml, Type xmlType)

              {

                  XmlSerializer ser = new XmlSerializer(xmlType);

                  object obj = null;

                  using (StringReader reader = new StringReader(xml))

                  {

                      obj = ser.Deserialize(reader);

                  }

                  return obj;

              }

       

              static void Main(string[] args)

              {

                  Player p = new Player();

                  p.Number = 23;

                  p.Name = "Dan";

                  string xml = GetXMLFromObject(p);

                  Console.WriteLine(xml);

                  Console.WriteLine();

       

                  Player q = (Player)CreateObjectFromXML(xml, typeof(Player));

                  Console.WriteLine(q.Number + " --> " + q.Name);

                  Console.ReadLine();

              }

      Other references:
      XML Serialization in the .NET Framework

      Wednesday, 27 December 2006 17:05:11 (GMT Standard Time, UTC+00:00)  #    Comments [1] -
      .NET | XML
      Navigation
      Archive
      <2017 June>
      SunMonTueWedThuFriSat
      28293031123
      45678910
      11121314151617
      18192021222324
      2526272829301
      2345678
      Blogroll
      About the author/Disclaimer

      Disclaimer
      The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

      © Copyright 2017
      Dan Miser
      Sign In
      Statistics
      Total Posts: 388
      This Year: 0
      This Month: 0
      This Week: 0
      Comments: 630
      Themes
      Pick a theme:
      All Content © 2017, Dan Miser
      DasBlog theme 'Business' created by Christoph De Baene (delarou)