Taoffi's blog

prisonniers du temps

Jet.oledb.4.0 and utf8 bom story

As you may know, a text file may specify its encoding by a ‘bom’ (byte order mark) using several bytes at its beginning. For utf8 encoding the signature bytes are: 0xef, 0xbb, 0xbf.

I came across an issue while manipulating csv files, for which I decided to use utf8 (thinking that was a good choice for a multi-cultural environment!). The process involved reading and writing back to the same file after some insertions and updates. All using microsoft.jet.oledb.4.0 provider (with a schema.ini specifying CharacterSet=65001 (65001 being utf8 code page)).

My csv files had a header row of which the first column was, ironically, named ‘Match ID’. A few manipulations revealed a somehow strange behavior. Although the debugger showed that the first column’s name is ‘Match ID’, I could no more access ‘Match ID’ column by its name. Using the watch window, I asked the debugger:
myColumn.ColumnName == "Match ID"… it replied false… weird!

Viewing the column name's CharArray in hexa offers a more significant information:

 column name issue

That is evidently endless! With the time going, as you manipulate your columns and rewrite back to the csv file, you end up by having your 'Match ID' column prefixed by bytes from the utf8 bom code as many times you rewrite the csv file. And if you are a nice guy who lets the users reorder the columns as they need, you may end up by having all your columns affected by that issue!

column name bytes

Changing files’ encoding to unicode (whose bom signature is 0xff 0xfe 0xff 0xfe) does not reproduce the issue. Which makes it clear that the source of annoyance is not utf8 but rather the jet.oledb.4 data provider with utf8. Still, identifying the source is half way of solving the issue :).

How to solve this?

Well, you may think of ‘sanitizing’ your column names at every load! Which, in my view, does not seem quite practical.
In my case I just switched to unicode (despite more bytes waste!) to preserve multi-cultural data requirements.

xsl witness!

Transforming xml content through xsl stylesheets is a useful and relatively common feature in the development process. I talked about this in the previous post about OneNote pages html preview.
Searching in my personal code toolbox, I just found this ‘iXslWitness’, a tool I wrote a couple of years ago to check the effectiveness of a stylesheet in transforming xml to html. Its usage is quite simple: you select an xml file and the xsl stylesheet to use. And you get the html transformed content.
I hope that can be useful for anyone involved in such tasks!
A screenshot of transforming a OneNote page xml content (a list of ‘The World If’ publications of The Economist newspaper):


You can download the tool Here.
The source code is Here.

OneNote page xsl transformation

As we saw in a previous post, OneNote API is xml-based. You call the OneNote Application object to obtain almost all needed information as xml strings.

One of that information is the page content. Whose schema is defined as explained in the previous post.

Once you get the page content’s xml string, it is a little bit of work to transform that into a useful html page

To do this, I used an xslt style sheet which is the subject of the current post.

How does it work?

Assume you have an xsl sheet string and the xml string of a page. You can then process both in a way similar to the following code:


using System.Xml.Xsl;


public static string XmlToHtml(string xmlString, string xslString)
    string            html;
    XslCompiledTransform    transform  = null;
    XmlReader         xslReader        = null,
                      xmlReader        = null;
    MemoryStream      memStream        = null;
    StreamReader      sr               = null;
    MemoryStream      xslStream        = null,
                      xmlStream        = null;
    byte[]            xslBytes         = Encoding.UTF8.GetBytes( xslString),
                      xmlBytes         = Encoding.UTF8.GetBytes( xmlString);

    xslStream    = new MemoryStream( xslBytes);
    xmlStream    = new MemoryStream( xmlBytes);

    transform    = new XslCompiledTransform();
    xslReader    = XmlReader.Create( xslStream);
    xmlReader    = XmlReader.Create( xmlStream);
    memStream    = new MemoryStream();

    transform.Load( xslReader);
    transform.Transform( xmlReader, null, memStream);

    memStream.Position    = 0;

    sr      = new StreamReader( memStream);
    html    = sr.ReadToEnd();

    return html;




How to get the page xml content?

Assuming you have the page ID, here is a sample code to query the page content through OneNote API:


public static string GetPageContentXmlString(string pageId)
    var         onenoteApp  = new Application();
    string      pageXml     = null;
    PageInfo    pageInfo    = PageInfo.piAll;

    onenoteApp.GetPageContent(pageId, out pageXml, pageInfo);
    return pageXml;


Reminder: The page content xsd schema


The xsl style sheet general structure

Let us use the iXml explorer to navigate through the xsl stylesheet used to transform the page’s xml into html.

(I searched for ‘match’ to locate templates defined in the stylesheet).

As you may notice, we have an xsl template to handle each OneNote page defined xsd type:

  • A template to process the page root information
  • A template to process the page’s title
  • A template to process outline elements
  • A template to process OEChildren collection
  • … and so forth

Sample xsl code

Process OneNote Element (one:OE)

  <xsl:template match="one:OE">
    <xsl:param name="nest_level" select="0" />

    <xsl:variable name="listNode" select="./one:List" />
    <xsl:variable name="quickStyleIndex" select="./@quickStyleIndex" />
    <xsl:variable name ="styleNode" select="msxsl:node-set($quickStyleList)/quickStyle[@index=$quickStyleIndex]" />

    <xsl:variable name="quickStyle">
        <xsl:when test="$styleNode">
          <xsl:value-of select="$styleNode/@style"/>

    <!-- is there any list here? -->
      <xsl:when test="$listNode">
        <xsl:variable name="number"    select="$listNode/one:Number" />
        <xsl:variable name="txt"      select="./one:T" />
        <xsl:variable name="listItemTag">

        <!-- list tag: either <ol> or <ul> -->
        <xsl:variable name="listTag">
            <xsl:when test="$number">

          <!-- numbered list? output <ol> -->
          <xsl:when test="$number">
            <xsl:variable name="txtNum"        select="number($number/@text)" />
            <xsl:variable name="fontNum"      select="$number/@font" />
            <xsl:variable name="tag" select="concat('<', $listTag, '>')" />
            <xsl:value-of disable-output-escaping="yes" select="$tag"/>

            <!-- *********** output <li value="xx"> ' style="font-family:', $fontNum, ';"',************* -->
            <xsl:value-of disable-output-escaping="yes" select="concat('<', $listItemTag, ' value=', '"', $txtNum, '">')" />

            <xsl:call-template name="outputListItem">
              <xsl:with-param name="listNode" select="$listNode" />
              <xsl:with-param name="itemText" select="$txt" />

          <!-- bullet ? output <ul> -->
            <xsl:variable name="tag" select="concat('<', $listTag, '>')" />
            <xsl:value-of disable-output-escaping="yes" select="$tag"/>
            <!-- *********** output <li> ************* -->
            <xsl:value-of disable-output-escaping="yes" select="concat('<', $listItemTag,'>')" />

            <xsl:call-template name="outputListItem">
              <xsl:with-param name="listNode" select="$listNode" />
              <xsl:with-param name="itemText" select="$txt" />


        <!-- process list's sub items -->
        <xsl:apply-templates select="./one:OEChildren">
          <xsl:with-param name="nest_level" select="1 + $nest_level" />

        <xsl:apply-templates select="./one:Table" />

        <!-- close the list item tag -->
        <xsl:value-of disable-output-escaping="yes" select="concat('</', $listItemTag,'>')" />
        <!-- close the list tag -->
        <xsl:value-of disable-output-escaping="yes" select="concat('</', $listTag, '>')"/>

      <!-- no list: process all sub items -->
        <xsl:variable name="style0" >
          <xsl:call-template name="string-replace-all">
            <xsl:with-param name="text" select="./@style" />
            <xsl:with-param name="replace" select="''" />
            <xsl:with-param name="by" select="''" />

        <xsl:variable name="alignment" select="./@alignment" />

        <xsl:variable name="style">
            <xsl:when test="$alignment='right'">
              <xsl:value-of select="concat('width:100%; float:right; display:inline; text-align:right;', $style0)"/>
              <xsl:value-of select="$style0"/>

          <xsl:when test="string-length($style)>0">
            <span style="{$style}">
              <xsl:apply-templates />

          <!-- ****** no style defined -->
              <xsl:when test="$quickStyle">
                <span style="{$quickStyle}">
                    <xsl:with-param name="nest_level" select="1 + $nest_level" />

                    <xsl:with-param name="nest_level" select="1 + $nest_level" />
          <!-- ****** end of : no style defined -->


Output a list (either numbered or bulleted)

  output list item (numbered / bulleted)
  <xsl:template name="outputListItem" match="one:List">
    <xsl:param name="listNode" />
    <xsl:param name="itemText" />

    <xsl:variable name="number"        select="$listNode/one:Number" />
    <xsl:variable name="bullet"        select="$listNode/one:Bullet" />
    <xsl:variable name="txtNum"        select="number($number/@text)" />

      <xsl:when test="$number">
        <xsl:value-of select="normalize-space($itemText)" disable-output-escaping="yes"/>

        <xsl:value-of select="normalize-space($itemText)" disable-output-escaping="yes"/>


Process page images

In the page’s xml, images are returned as base64 strings.

To process an image into html, the xsl template looks like the following:

  <xsl:template match="one:Image">
    <xsl:variable name="imgWidth"select="substring-before( number(./one:Size/@width) * 1.33, '.')"/>
    <xsl:variable name="imgHeight" select="substring-before( number(./one:Size/@height) * 1.33, '.')"/>
    <xsl:variable name="imgData"    select="./one:Data" />
    <xsl:variable name="oneFormat"  select="./@format" />
    <xsl:variable name="htmlformat">
        <xsl:when test="$oneFormat='png'">

    <xsl:variable name="htmlWidth">
        <xsl:when test="$imgWidth">
          <xsl:value-of select="$imgWidth"/>

    <xsl:variable name="htmlHeight">
        <xsl:when test="$imgHeight">
          <xsl:value-of select="$imgHeight"/>

    <img width="{$htmlWidth}" height="{$htmlHeight}" src="{$htmlformat}, {$imgData}"/>


Download the xsl stylesheet

You may download the entire xsl stylesheet (for OneNote 2013 and 2016) here

Json object explorer

[json objects =>to property bags =>to objects]

Reducing dependency between clients and services is a major common question in software solutions.

One important area of client/server dependencies lies in the structure of objects involved in exchanged messages (requests / responses). For instance: a new property inserted to an object on service side, often crashes the other side (client) until the new property is introduced on the involved object.

I previously posted about loose coupling through property bags abstractions.

My first approach was based on creating a common convention between service and client which implies transforming involved objects into property bags whose values would be assigned as needed to business objects at each side on runtime. That still seems to be a 'best solution' in my point of view.

Another approach is to transform the received objects (at either side: server/client) into property bags before assigning their values to the related objects.

This second approach is better suited for situations where creating a common convention would be difficult to put in place.

While working on some projects based on soap-xml messages, I wrote a simple transformer: [xml => property bags => objects].The transformer then helped write an xml explorer (which actually views xml content as its property bag tree. You can read about this in a previous post).

Another project presented a new challenge in that area, as the service (JEE) was using Json format for its messages. In collaboration with the Java colleagues, we could implement the property bag approach which helped ease client / server versioning issues.

A visual tool, similar to xml explorer, was needed for developers to explore json messages' structures. And that was time for me to write a new json <==>-property bag parser.

The goal was to:

  • Transform json content to property bags
  • Display the transformed property bag tree

Using Newtonsoft's Json library – notably its Linq extensions – was essential.

Hereafter the global dependency diagram of the Json explorer app:


The main method in the transformation is ParseJsonString to which you provide the string to be parsed.

Its logic is rather simple:

  • A json string is the representation of either:
    • An object:
      • Read its properties (which may contain arrays… see below)
    • Or an array of:
      • Objects: read the array's objects
      • Arrays: read the array's arrays


Code snippets

The parse json string method

public static PropertyBag ParseJsonString(string jsonString)
    JObject jObj = null;
    PropertyBag bag = new PropertyBag("Json");
    ObjProperty bagRootNode;
    JArray jArray = null;
    string exceptionString = "";

    /// the json string is either:
    /// * a json object
    /// * a json array
    /// * or an invalid string

    // try to parse the string as a JsonObject
        jObj = JObject.Parse(jsonString);
    catch (Exception ex)
        jObj = null;
        exceptionString = ex.Message;

    // try to parse the string as a JArray
    if(jObj == null)
            jArray = JArray.Parse(jsonString);
        catch (Exception ex2)
            jArray = null;
            exceptionString = ex2.Message;

        if(jArray == null)
            bag.Add(new ObjProperty(_exceptionString, null, false) { ValueAsString = exceptionString });
            return bag;

    bagRootNode = new ObjProperty("JsonRoot", null, false);

    if(bagRootNode.Children == null)
        bagRootNode.Children = new PropertyBag();


    if(jObj != null)
        bagRootNode.SourceDataType = typeof(JObject);
        bagRootNode.Children = ParseJsonObject(bagRootNode, jObj);
    else if(jArray != null)
        bagRootNode.SourceDataType = typeof(JArray);
        bagRootNode.Children = ParseJsonArray(bagRootNode, jArray);

    return bag;


Parse json array code snippet


private static PropertyBag ParseJsonArray(ObjProperty parentItem, JArray jArray)
    if(parentItem == null || jArray == null)
        return null;

    ObjProperty childItem;

    if(parentItem.Children == null)
        parentItem.Children = new PropertyBag();

    PropertyBag curBag        = parentItem.Children;

    foreach(var item in jArray.Children())
        JObject jo     = item as JObject;
        JArray subArray = item as JArray;
        PropertyBag childBag;
        Type nodeType = subArray != null ? typeof(JArray) : typeof(JObject);

        childItem    = new ObjProperty("item", parentItem, false) { SourceDataType = nodeType };

        if (jo != null)
            childBag = ParseJsonObject(childItem, jo);
        else if(subArray != null)
            childBag    = ParseJsonArray(childItem, subArray);


    return curBag;


Json to Xml

As, now, we have the json content in property bags, we can almost directly get the xml equivalent (see screenshot below).

The used sample json string: for the following screenshot:


    "web-app": {
    "servlet": [
        "servlet-name": "cofaxCDS",
        "servlet-class": "org.cofax.cds.CDSServlet",
        "init-param": {
            "configGlossary:installationAt": "Philadelphia, PA",
            "configGlossary:adminEmail": "ksm@pobox.com",
            "configGlossary:poweredBy": "Cofax",
            "maxUrlLength": 500
        "servlet-name": "cofaxEmail",
        "servlet-class": "org.cofax.cds.EmailServlet",
        "init-param": {
            "mailHost": "mail1",
            "mailHostOverride": "mail2"
        "servlet-name": "cofaxAdmin",
        "servlet-class": "org.cofax.cds.AdminServlet"

        "servlet-name": "fileServlet",
        "servlet-class": "org.cofax.cds.FileServlet"
        "servlet-name": "cofaxTools",
        "servlet-class": "org.cofax.cms.CofaxToolsServlet",
        "init-param": {
            "templatePath": "toolstemplates/",
            "log": 1,
            "adminGroupID": 4,
            "betaServer": true
    "servlet-mapping": {
        "cofaxCDS": "/",
        "cofaxEmail": "/cofaxutil/aemail/*",
        "cofaxAdmin": "/admin/*",
        "fileServlet": "/static/*",
        "cofaxTools": "/tools/*"

    "taglib": {
        "taglib-uri": "cofax.tld",
        "taglib-location": "/WEB-INF/tlds/cofax.tld"



You may download the binaries here!

The source code is available here!

OneNote Explorer

In January 2004, Chris Pratley wrote about "OneNote genesis". His article ended by this sentence: "…I can see how this might become addictive."

Yes, as many people who know OneNote often use the word, "addictive" is a correct adjective for OneNote.

What makes it addictive is probably the fact that it is a medium for 'not-yet-documented' ideas. In the same time, it offers a good and simple hierarchical storage that helps organize those ideas for future documentation.

One great thing is that OneNote exposes its objects and methods for developers through an API for extending its features. There are many feature-rich add-ins for OneNote, which can fit your needs in several areas.

In my case, I needed a sort of 'periscope' to explore my own notes. A tool that can let me see my notes ordered by creation or last update dates, mark and retrieve some of them as favorite items, have a quick preview of a note, locate the section's file folder, search notes' titles and/or content… etc.

Using the API, I could write a 'OneNote Explorer'… a tool I started writing in 2010, enriching it with new features from time to time.

OneNote API

OneNote API is xml-based. A set of methods in the Application Interface let you get information about opened notebooks and their structures (section groups, sections, pages… etc.) in xml format.
Understanding OneNote xsd schema is thus essential.

OneNote XSD overview: main objects

 onenote xsd

  • A Notebook is (similar to file folder) a sequence of:
    • Sections
    • And/or Section groups. Where a Section group itself is a sequence of:
      • Section groups
      • And/or Sections. Where a Section is a sequence of:
        • Pages.

OneNote Page definition

onenote page xsd

  • Apart from its attributes (see xsd elements above), a Page is a set of either:
    • An Image
    • A Drawing
    • A File
    • A Media
    • An Outline (similar to html main <div>) which is (somewhat simplified here) is a sequence of:
      • OE children (OneNote Elements). Each OE can be either:
        • An Image
        • A Table
        • Drawing
        • Or a sequence of:
          • T (text range)

Application overview

Application view model classes:

 application main classes


A static class (OneNoteHelpers) exposes several methods to communicate with OneNote API and create / update the view model objects as required:

 code map 1

Summary of methods exposed by the helper static class:

 onenote helpers


  • View selected section pages. Search titles, sort the datagrid, add page to favorites, open page in OneNote, html preview

feature 1

  • View all notebook pages. Search titles, sort the datagrid, add page to favorites, open page in OneNote, html preview

feature 2

  • Search selected notebooks

feature 3

  • Manage favorites: delete, preview, open in OneNote…

feature 4

Page preview note

The application's Preview button displays the html content of the selected page. As OneNote API can return the page xml content, an xslt style sheet (with templates per each element type of the xsd definition) allows a simple and quick preview.

sample page 

The simple page's xml tree

sample page's xsd

The page xml code

<?xml version="1.0" encoding="utf-8"?>
<one:Page xmlns:one="http://schemas.microsoft.com/office/onenote/2013/onenote"
         name="Sample page title" dateTime="2018-04-20T18:53:38.000Z"
<!-- ***************** quick styles ***************************** -->
<one:QuickStyleDef index="0"
                     font="Calibri Light"
                     fontSize="20.0" spaceBefore="0.0" spaceAfter="0.0" />
<one:QuickStyleDef index="1"
                     spaceBefore="0.0" spaceAfter="0.0" />
<!-- ********** page settings ********** -->
<one:PageSettings RTL="false" color="automatic">
<one:Automatic />
<one:RuleLines visible="false" />
<!-- ********** title ********** -->
<one:Title selected="partial" lang="en-US">
<one:OE author="taoffi" authorInitials="T.N."
            quickStyleIndex="0" selected="partial">
<one:T><![CDATA[Sample page title]]></one:T>
<one:T selected="all"><![CDATA[]]></one:T>
<!-- ********** page content (main <div>) ********** -->
<one:Outline author="taoffi"
<one:Position x="36.0" y="86.4000015258789" z="0" />
<one:Size width="123.9317169189453" height="14.64842319488525" />
        <!-- ********** paragra^ph ********** -->
<one:OE creationTime="2018-04-20T18:53:47.000Z"
         <!-- ********** paragraph text ********** -->
<one:T><![CDATA[Sample page text]]></one:T>


OneNote 2010 vs. 2013 and above

There are some compatibility issues between OneNote API for 2010 version and 2013 and above. More changes have been introduced in 365 version.

The downloadable binaries here are for OneNote 2013 and 2016 desktop.

You may download the binaries Here!

The social vs. networking

Numerous of the latest events reveal as much of collisions between technology and social activities.

You may have a look at some of Zeynep Tufekci's articles to get an idea about how broad the problem is.

Information Technology seems to have grownup immersed in its own technical problems with little regard to the social role it might (or might have to) play.

It is somehow astonishing, for instance, to watch how a company like Facebook does not seem to grasp few simple responsibilities about what it may / may not sell or buy and to whom. And how it came up at the end by admitting that a 'human' check is required over ads sold on its network!

Definitely, some technology companies seem to have grown up from their technical issues to at least one social notion: profit.

Unfortunately that cannot be enough. May they just recall that even profit is constrained by laws and, accessorily, some fundamental ethics!

Thuggish practices in businesses

I keep being surprised of the number of unmentioned violent incidents we live everyday while condemning violence is a common theme in all occasions. We seem to agree that exerting violence in some form is condemnable, but accept (or at least keep unmentioned) other forms of violence that are often the seeds of the condemnable type.

One common type of violence, that many people live without even having the right to talk about, is violence exerted in the workplace. Harassment in businesses is more and more a common practice. It even seems to have been elevated to some high level of craftsmanship or art, all with its own techniques!

If we try to summarize violence as an act of offering the choice of: 'Do that or otherwise die' / 'You did not do that, you deserve dying', that would exactly be the significance of harassment in the workplace: 'Do that or otherwise be fired' / 'You did not do that, you deserve being fired'. Where being 'fired' ultimately means: have no resources, and, most probably Die! (Or at least, join those beggars you just met in your commute this morning!)

I can hardly consider such situations otherwise than a violence exerted on people.

I wanted to talk about this subject after having found myself in a real situation during a mission at a small company where nervousness among the people was perceptible in a way I did not see before. In the workplace, you could easily guess who are the 'foremen' specialized in people harassment (themselves being harassed by others …less visible!). The thick ambiance all being clothed into artificial ways of 'humanization' through – more or less superficial – parties, drinks, games and the like. But which could not mask the ambient anxiety.

On the ethical side, such violence is questionable.

Not surprisingly, on the productivity side that had negative effects too. You cannot be creative nor productive by fear.

The global technical level and practices of the company were rather 'low' by many standard measures. But you could not find an ear that may accept changes, or just accept discussing change proposals. The thick ambiance turned the business activity into sclerosed processes deaf to change. 'Change' became Fearful!

All that activity (and violence) were of course performed through, allegedly, 'Agile' and other artifacts which are sometimes just words decorating the worst unethical practices and bad results you can imagine!


Anecdotally, the company's business was: 'to help businesses in investigating unethical practices'!

No need to mention: I was fired J

Xamarin: the missing Description attribute

If you are a Windows C# programmer, you may know about the DescriptionAttribute and its help in describing an object, a property, method or any other member of a class in a human way.

You may also use [Description], to associate a Label to a property and later use it in the UI.

As Xamarin.Forms does not (yet) offer this simple useful attribute, I decided to write one.

The basic code

Our Description attribute class is quite simple:

[AttributeUsage(validOn: AttributeTargets.All, AllowMultiple = false, Inherited = false)]
public class DescriptionAttribute : Attribute
    public string _description;

    public DescriptionAttribute(string description)
         _description = description;

    public string Description
        get { return _description; }
        set { _description = value; }


With this in place, we can now write things like:

[Description("This is my object")]
public class MyClass
    [Description("This is my constructor")]
    public MyClass()

    [Description("My property")]
    public string Property1



Reading back the descriptions

Well, but for this to be useful, we must do something to get back these descriptions when needed.

First: how to read the descriptions assigned to objects and members?

Some extension helpers can simplify this work (remember: we are in portable (PCL) library, and also using System.Reflection):

public static string Description(this Type objectType)
    if(objectType == null)
        return null;

    TypeInfo typeInfo = objectType.GetTypeInfo();
    var attrib = typeInfo.GetCustomAttribute<DescriptionAttribute>();
    return attrib == null ? null : attrib.Description;

To get the description of MyClass, The above extension method now allows us to write:

string    classDescription    = typeof(MyClass).Description();


Another method may even make that simpler: get the description of an object's instance of a given class:

public static string Description(this object obj)
    if(obj == null)
        return null;

    return obj.GetType().Description();


This allows us to write: myObject.Description(); to get the description of myObject's class.

Reading back the description of class members

Reading a given member (property / method…) description, we have to look into the MemberInfo object of that given member to find the Description attribute:


public static string MemberDescription(this MemberInfo member)
    if(member == null)
        return null;

    var attrib = member.GetCustomAttribute<DescriptionAttribute>();
    return attrib == null ? null : attrib.Description;



How to get a member info? Not quite handy!...

Let us simplify a little more. The following code (though it may be somehow difficult to read… see System.Linq.Expressions) will allow a much easier syntax.


public static string PropertyDescription<TMember>( Expression<Func<TMember>> memberExpression)
    if (memberExpression == null)
        return null;

    var expression = memberExpression.Body as MemberExpression;
    var member = expression == null ? null : expression.Member;

    if (member == null)
        return null;

    return member.MemberDescription();



The above method analyses its Expression parameter to extract the MemberInfo for us and calls the original method to extract the description of the member.

To use this method to extract the description of 'Property1' , we can write:

string propertyLabel = PropertyDescription(()=> Property1);


What about Enums?

As you know, we often give short (occasionally cryptic!) names for enum members. Displaying these names in a clear human-readable manner to the user for selecting a value is usually a challenge.

The Description attribute can help us assign these labels. Reading them back is somehow another challenge. The reason is that enum members are fields (in contrast to member properties and methods we saw before)

Actually, with enums, we have two challenges: find the description of each element, but also be able to retrieve the value of a selected description.

For the first challenge, find the description of an element, let us try this extension:


public static string EnumDescription(this Enum value)
    if(value == null)
        return null;

    var type = value.GetType();
    TypeInfo typeInfo = type.GetTypeInfo();
    string typeName = Enum.GetName(type, value);

    if (string.IsNullOrEmpty(typeName))
        return null;

    var field = typeInfo.DeclaredFields.FirstOrDefault(f => f.Name == typeName);

    if(field == null)
        return typeName;

    var attrib = field.GetCustomAttribute<DescriptionAttribute>();
    return attrib == null ? typeName : attrib.Description;



Sample usage:


public enum Flowers
    [Description("African lily")]

    [Description("Alpine thistle")]

    [Description("Amazon lily")]


string africanLilly = Flowers.Agapanthus.EnumDescription(); //"African lily"
string alpineThistle = Flowers.Eryngium.EnumDescription(); //"Alpine thistle"


Find the enum value by its description

The second task is to retrieve the enum value by its description. For instance when the user selects one of the displayed descriptions.


public static int EnumValue(this Enum value, string selectedOption)
    var values = Enum.GetValues(value.GetType());

    foreach(Enum v in values)
        string description = v.EnumDescription();

        if(description == selectedOption)
            return (int) v;

    return 0; // arbitrary default value



Now we can write:


Flowers africanLilly = Flowers.EnumValue("African lily");    // Agapanthus
Flowers amazonLilly = Flowers.EnumValue("Amazon lily");    // Eucharis