May 09 2008

String.Format and HTML string

Published by Raja Nadar at 9:22 pm under .net, c#, css, reflector

I was working with an email component, where different mails needed to be sent based on business scenarios. these emails were html formatted, and localization prone.. hence the html content was stored in resource files. I like the strongly-type resources in .NET 2.0 and above.

the whole html was not static, and hence it had placeholders (format strings) to insert business data values, during their actual use.

so a code snippet to construct the email subject would look like: 

string mailSubject = String.Format(CultureInfo.CurrentCulture,
Resource. EmailSubjectKey, blahObject.Id, blahObject.Name);

when I was unit testing the code snippet, I found that the above line gave me a Format exception. I checked the resource string. the Resource.EmailSubjectKey apparently had a valid content with the format strings {0} and {1} for Id and Name. no issues so far..

curious for the behind the scene action, I reflected on the String.Format method, and found that it internally called the StringBuilder.AppendFormat method, which is as follows: 

 

public StringBuilder AppendFormat(IFormatProvider provider,
string format, params object[] args)
{
    // some top level blah blah..    
    while (index < length)
    {
        ch = chArray[index];
        index++;
        if (ch == '}')
        {
            if ((index < length) && (chArray[index] == '}'))
            {
                index++;
            }
            else
            {
                FormatError();
            }
        }
        if (ch == '{')
        {
            if ((index < length) && (chArray[index] == '{'))
            {
                index++;
            }
            else
            {
                index--;
                break;
            }
        }
        chArray[num4++] = ch;
    } // some more blah..

at this point, I realized that curly braces might be the issue. I checked back my html and sure enough, I was using inline css. 

 

    &;lt;style type="text/css"&;gt;
        .title
        {
        margin-left: 10px;
        font-family: Calibri, Verdana, Tahoma;
        font-size: small;
        } 
    &;lt;/style&;gt;

the AppendFormat chartered into the CSS curly braces and hence,  the unit case failed and the Format exception. now I had 2 solutions for this:

  • attribute based styles: (further inline css)
  • con the AppendFormat method..

I had a single CSS class for the whole Email, and hence the following attribute based style works: 

 

<body style="margin-left: 10px; font-family:
Calibri, Verdana, Tahoma; font-size: small;">

but if you are figuring out how to get past the AppendFormat method, notice the snippet: 

        if (ch == '{')
        {
            if ((index < length) && (chArray[index] == '{'))
            {
                index++;
            }

if the method finds 2 consecutive opening braces ‘{‘, it bypasses it and does not do any format string substitution. that means, the following works perfectly well.

 

&;lt;style type="text/css"&;gt;
        .title
        {{
        margin-left: 10px;
        font-family: Calibri, Verdana, Tahoma;
        font-size: small;
        }} 
&;lt;/style&;gt;

so now, the above snippet actually puts things in place. AppendFormat doesn’t wander into the CSS area. the CSS engine doesn’t mind the duplicate braces, either.

there’s a solution to every problem; given enough time and money..

Trackback URI | Comments RSS

Leave a Reply