Scott Hanselman

Making the XmlSerializer output alternate values for simple types

September 01, 2005 Comment on this post [4] Posted in ASP.NET | XmlSerializer
Sponsored By

Given a class like this:

public class Student
{
    public int SSN = 555555555;
    public decimal GPA = 0.1;
    public bool cool = false;
    public DateTime birthday = DateTime.Now;
    public long Height = 80;
}

The XmlSerializer will output XML like this:

<Student>
  <SSN>555555555</SSN>
  <GPA>0.1</GPA>
  <cool>false</cool>
  <birthday>2005-09-01T13:25:41.4964384-07:00</birthday>
  <Height>60</Height>
</Student>

As you'd expect. Note the standard 8601 DateTime and the word "false" for the boolean element "cool."

However, what if you want to output "bar" for false and "foo" for true? Here's one way that we've built into some code generation templates. The trick is that the actual boolean that the developer accesses is marked as XmlIgnore, and a parallel string value is marked with and [XmlElement] attribute that changes the name of the serialized element.

    1 using System;
    2 using System.Xml;
    3 using System.Collections;
    4 using System.Xml.Serialization;
    5 using System.IO;
    6 
    7 public class SerTest
    8 {
    9     public static void Main(string[] args)
   10     {
   11         Student[] students = new Student[2];
   12 
   13         students[0] = new Student();
   14         students[0].SSN = 555555555;
   15         students[0].GPA = 0.1M;
   16         students[0].Height = 60;
   17         students[0].cool = false;
   18 
   19         students[1] = new Student();
   20         students[1].SSN = 555554444;
   21         students[1].GPA = 3.1M;
   22         students[1].Height = 160;
   23         students[1].cool = true;
   24 
   25 
   26         XmlSerializer mySerializer = new 
   27             XmlSerializer(typeof(Student[] ));
   28 
   29         StreamWriter myWriter = new StreamWriter("Students.xml");
   30         mySerializer.Serialize(myWriter, students);
   31 
   32         myWriter.Close();
   33         StreamReader myReader = new StreamReader("Students.xml");
   34         Student[] somefolks = (Student[])mySerializer.Deserialize(myReader);
   35     }
   36 }
   37 
   38 public class Student
   39 {
   40     public int SSN;
   41 
   42     public decimal GPA;
   43 
   44     //It is assumed that the values "FOO" and "BAR" are put here by
   45     // a code generator, so it's not that big of a deal that they are 
   46     // duplicated in this code. Just trying to cover all bases. 
   47     [XmlIgnore]
   48     public bool cool
   49     {
   50         get
   51         {
   52             if (coolStringValue == null || coolStringValue.Length == 0) return false;
   53 
   54             if (CaseInsensitiveComparer.DefaultInvariant.Compare(coolStringValue,"FOO") == 0)
   55             {
   56                 return true;
   57             }
   58             else if (CaseInsensitiveComparer.DefaultInvariant.Compare(coolStringValue,"BAR") == 0)
   59             {
   60                 return false;
   61             }
   62             throw new ApplicationException(coolStringValue + " 
is neither FOO (true) nor BAR (false). This is an invalid state for this boolean.");
   63         }
   64         set
   65         {
   66             coolStringValue = (value ? "FOO" : "BAR" );            
   67         }
   68     }    
   69     [XmlElementAttribute(ElementName="cool",DataType="string")]
   70     public string coolStringValue = "bar";
   71 
   72     public DateTime birthday = DateTime.Now;
   73 
   74     public long Height = 80;
   75 }

This code listing outputs this XML:

<?xml version="1.0" encoding="utf-8"?>
<ArrayOfStudent xmlns:xsd="
http://www.w3.org/2001/XMLSchema
       xmlns:xsi="
http://www.w3.org/2001/XMLSchema-instance">
  <Student>
    <SSN>555555555</SSN>
    <GPA>0.1</GPA>
    <cool>BAR</cool>
    <birthday>2005-09-01T13:35:31.0041088-07:00</birthday>
    <Height>60</Height>
  </Student>
  <Student>
    <SSN>555554444</SSN>
    <GPA>3.1</GPA>
    <cool>FOO</cool>
    <birthday>2005-09-01T13:35:31.0041088-07:00</birthday>
    <Height>160</Height>
  </Student>
</ArrayOfStudent>

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook bluesky subscribe
About   Newsletter
Hosting By
Hosted on Linux using .NET in an Azure App Service

PSP Playstation Portable 2.0 Firmware Update

August 24, 2005 Comment on this post [3] Posted in Reviews | Gaming
Sponsored By

System_updates2_head2Just wirelessly downloaded the new PSP 2.0 Firmware. New features include a legit Web Browser which makes the PSP finally useful enough to carry in my bag with me. Also new in the 2.0 release is a Wallpaper feature, new graphics format support, support for unprotected AAC and WAV audio files which should please my iTunes collection.

This device has so much potential it's ricockulous.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook bluesky subscribe
About   Newsletter
Hosting By
Hosted on Linux using .NET in an Azure App Service

Baby Registry

August 24, 2005 Comment on this post [6] Posted in Musings
Sponsored By

Registry-btnIf you're a relative and you've stumbled on this technical blog, here's our Baby Registry. For the .NET Technical folks, move along, nothing to see here! :)

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook bluesky subscribe
About   Newsletter
Hosting By
Hosted on Linux using .NET in an Azure App Service

You must implement the Add(System.Object) method on MyClass because it inherits from IEnumerable

August 23, 2005 Comment on this post [3] Posted in ASP.NET | Learning .NET | XmlSerializer | Africa
Sponsored By

Peter was getting the error "You must implement the Add(System.Object) method on MyClass because it inherits from IEnumerable" while serializing an object. He added an Add() method and the error went away, but he was rightfully confused by this odd message because IEnumerable doesn't require an Add as part of its contract! The error message arguably uses the word "implement" in a way that implies something about the interface in question.

Remember that the XmlSerializer has to serialize and deserialize, and does so only via public means. For something that implements IEnumerable, there'd be no way to get objects back in without something like an Add.

Sairama pointed to this paragraph buried in the MSDN docs:

The XmlSerializer gives special treatment to classes that implement IEnumerable or ICollection. A class that implements IEnumerable must implement a public Add method that takes a single parameter. The Add method's parameter must be of the same type as is returned from the Current property on the value returned from GetEnumerator, or one of that type's bases. A class that implements ICollection (such as CollectionBase) in addition to IEnumerable must have a public Item indexed property (indexer in C#) that takes an integer, and it must have a public Count property of type integer. The parameter to the Add method must be the same type as is returned from the Item property, or one of that type's bases. For classes implementing ICollection, values to be serialized will be retrieved from the indexed Item property, not by calling GetEnumerator

Now playing: Ladysmith Black Mambazo - N'kosi Sikeleli Afrika (God Bless Africa)

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook bluesky subscribe
About   Newsletter
Hosting By
Hosted on Linux using .NET in an Azure App Service

The ISAPI equivalent of Response.AppendToLog

August 23, 2005 Comment on this post [1] Posted in ASP.NET | Web Services
Sponsored By

In ASP.NET the Response object has a very useful method called AppendToLog. It was also around in the Classic ASP days. The Response object hangs off the HttpContext. If you're running with the context of an HttpRequest you can always get ahold of the current HttpContext via the static HttpContext.Current.

However, not everyone executes within managed code in ASP.NET. We've got a bunch of ISAPI code that is all C++/ATL/MFC. Within MFC you can get ahold of the context via the CHttpServerContext class. This class isn't as friendly as the whole Request/Response ASP model.

If you want to get to the really useful stuff you have to run through a 3rd Class API actually named ServerSupportFunction that's hanging off an Extension Control Block. Lame. The second parameter is a DWORD that indicates the function you're trying to call. Since we were trying to call the equivalent of Response.AppendToLog we would use HSE_APPEND_LOG_PARAMETER. The additional information you're trying to log will show up in the cs-uri-query extended field within IIS if you're using the W3C Extended Log File Format. You'll need to go into IIS Properties and enable the logging of this field.

So, doing this in managed code:

HttpContext.Current.Response.AppendToLog(strFoo);

Is this in unmanaged "classic" C++ ISAPI:

m_pCHttpServerContext->m_pECB->ServerSupportFunction( 
                                m_pCHttpServerContext->m_pECB->ConnID , 
                                HSE_APPEND_LOG_PARAMETER , 
                                szFoo, 
                                &dwFooLen , 
                                NULL 
                            );

Big ups to Paul Gomes from Corillian for figuring this out! And no I'm not off vacation yet; my wife is asleep. :)

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook bluesky subscribe
About   Newsletter
Hosting By
Hosted on Linux using .NET in an Azure App Service

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