What is the best way to create HTML in C# code?

  • I have a belief that markup should remain in mark-up and not in the code behind.

    I've come to a situation where I think it is acceptable to build the HTML in the code behind. I'd like to have some consensus as to what the best practices are or should be.

    When is it acceptable to build html in the code behind? What is the best method to create this html? (example: Strings, StringBuilder, HTMLWriter, etc)

    try using templates and placeholders where you will spit this html mark-ups.

    Another option: produce XML based on your data model and then use XSLT to turn the XML into HTML.

    Just came to my notice today C#/XAML for HTML5, look promising and may suit your scenario. http://cshtml5.com/

    a problem with the XSLT route is in localization. If you need two languages, you need two XSLT stylesheets and keep them parallel. That's hell. Better just write HTML to a text file from C#. use String.Format and $"..{variable}..." together with WPFLocalization ?

    It looks like you want Web Forms. Unfortunately for that endeavour, it is currently out of fashion.

  • Is using something like Razor not applicable here? Because if you're doing a lot of html generation using a view engine can make it a lot easier. It was also built to be used outside of ASP.NET.

    However sometimes that's not what you need. Have you considered using the TagBuilder class which is part of .net (mvc)? There is also the HtmlWriter in System.Web.UI (for web forms). I would recommend one of these if you are making Controls or Html Helpers.

    +1, if you need templating within an app razor is the way to go. Check out razorengine @ http://nuget.org/packages/RazorEngine if you need a great option for mounting razor within a non-asp.net app.

    I have a similar requirement where I need to generate html(loads of it) in a class library. I want to use razor for this but struggle to understand how to maintain cshtml files in a dll. How can it bundle together?

  • I would use the Html Agility Pack to assemble HTML and then write it out to a text file.

    A lot of man-hours went into making the Html Agility Pack robust and HTML-compliant HTML-friendly.

    I think it even includes a sample application that generates HTML.

    From the home page:

    Sample applications:

    Page fixing or generation. You can fix a page the way you want, modify the DOM, add nodes, copy nodes, well... you name it.

  • I would use htmltags to create HTML.

    Example:

    var tag = new HtmlTag("span")
        .Text("Hello & Goodbye")
        .AddClass("important")
        .Attr("title", "Greetings")
    

    And then CSQuery if I want to parse HTML

    Example:

    dom.Select("div > span")
        .Eq(1)
        .Text("Change the text content of the 2nd span child of each div");
    
  • There are, of course, libraries out there, such as HTML Agility Pack that can assist you in these endeavors.

    If you realy don't want to use an existing library, and want simple, down-and-dirty code, I like the idea of abstracting out some of the behaviors like a previous answer stated. I also like the idea of using an underlying StringBuilder, as opposed to a string for a couple reasons:

    1. Strings are less efficient than string builder
    2. StringBuilder is an indexable data structure,

    If I don't need a massively engineered HTML engine, I'd build a simple, intuitive interface

    AddLineBreak();
    AddSimpleTag(string tagName);
    AddSimpleTagAt(string tagName, string content, int index);
    Output();
    

    The indexable data structure is compelling, but I wouldn't worry *too* much about efficiency: http://www.codinghorror.com/blog/2009/01/the-sad-tragedy-of-micro-optimization-theater.html

    I've gotten bit a few times on the heaviness of Strings, especially REALLY big strings. StringBuilders are more memory efficient and processor efficient when they get big. So, in an implementation like this, where the HTML can get really big, I would start off with a StringBuilder. If there were a guarantee that the HTML was not going to get very big, a string would certainly be adequate.

    Well if the HTML can get really big, then I would certainly recommend the HTML Agility Pack. [I actually recommended the HTML Agility Pack two minutes before you did. :) ]

  • If you do end up using just strings, don't forget to escape all the HTML reserved characters in your output data.

    &    &
    >    >
    <    &lt;
    "    &quot;
    '    &apos;
    

    I recommend using an HTML-aware class or library instead of working directly with strings, though. HTMLWriter looks like a pretty good start.

    Thank you for this insight. For whoever this may read, this is what i use to pass the values of a datatable in an item template. The key is (as Mike Clark suggests) to be HTML aware:

  • FLAME ON!

    var html = "";
    html += "<table class='colorful'>";
    foreach(var item in collection) {
         html += "<tr>";
         html += "<td class='boldCell'>" + item.PropWhatever + "</td>";
         // more cells here as needed
         html += "</tr>";
    }
    html += "</table>";
    placeholder1.InnerHtml = html;
    

    I will prob get downvoted for this, but as a former designer who had to tweak HTML in code before I really knew much about .NET, the above code was way easier to understand than the methods that abstract HTML creation. If you think a designer might ever have to tweak your HTML, use simple strings like this.

    Something I see a lot of devs miss when they write HTML in code is that in HTML, single or double quotes are allowed for attributes. So instead of escaping all the quotes in code (which looks wanky as hell to the non-initiated), just use single quotes for the html quotes inside your strings.


    FINE. All you string concatenating haters are crampin' my rep. Here's the 'proper' way to do this without string concatenation, but I stand by my opinion that any normal page with normal tables won't present any performance problems outside of some ridiculous Google-like scale:

    var sb = new System.Text.StringBuilder();
    sb.Append("<table class='colorful'>");
    foreach (var item in collection)
    {
         sb.Append("<tr>");
         sb.Append("<td class='boldCell'>" + item.PropWhatever + "</td>");
         // more cells here as needed
         sb.Append("</tr>");
    }
    sb.Append("</table>");
    placeholder1.InnerHtml = sb.ToString();
    

    -1 using + to concatenate strings in loops is the worst thing you can do.

    Well, for starters, using `+=` inside a loop this way doesn't scale at all; because strings are immutable, you're creating a brand new string each time you do it. Use a `StringBuilder` instead.

    If this is javascript, a better approach is to use a array and push items to it and then use join to output the html-string. And the for-in loop is not a good approach either in js.

    Why must people who write horrible code share their horrible code with other people.

    @Ramhound What about `If you think a designer might ever have to tweak your HTML, use simple strings like this.` is hard to understand? Some peoples definition of horrible code is the one that buys milliseconds of performance at the cost of taking many seconds to fully understand. Clearly when you anticipate your code being viewed or maintained by the lowest common denominator of individual, the case can most certainly be made that writing code that is easier to understand or tweak is always better than the cleanest or best performing code.

    @Lavinski you are correct for large loops, but concatenation of strings in loops less than 10 iterations or so in size are probably faster than using StringBuilder. And I'm assuming there's kind of a natural limit to the number of table rows here (prob less than 200 or so) because you would not typically put that many on a screen. So honestly, there are FAR worse things I could be doing.

    @Graham no sorry string builder is faster even if it's just four strings. Strings are immutable, never ever use += in a loop. You just don't ever risk it.

    well it's more like 10 strings (see link) but then the GC also has extra work to do. Also I don't thing using append is any harder than using the plus operator. http://www.codeproject.com/Articles/14936/StringBuilder-vs-String-Fast-String-Operations-wit

    Just overload the `+` operator to use a StringBuilder. Yeah, that'll work.

  • Nearly two years after the original post - here is a solution that has worked well for me. In the target document I place the following:

    <table>    
        <%:theHtmlTableMomToldYouAbout() %>    //# Where I want my rows of table data to go
    </table>
    

    the function being called looks like this:

        public HtmlString theHtmlTableMomToldYouAbout()
        {
            string content = "";
            HtmlString theEnvelopePlease = null;
    
            for (int i = 0; i < 5; i++)
            {
                content = content + "<tr><td>The Number Is: " + i + "</td></tr>";
            }
            theEnvelopePlease = new HtmlString(content);
            return theEnvelopePlease;      
        }
    

    And the resulting output in the browser is as expected:
    The Number Is: 0
    The Number Is: 1
    The Number Is: 2
    The Number Is: 3
    The Number Is: 4

    When I go to view source I find the following:

    <table>
        <tr><td>The Number Is: 0</td></tr>
        <tr><td>The Number Is: 1</td></tr>
        <tr><td>The Number Is: 2</td></tr>
        <tr><td>The Number Is: 3</td></tr>
        <tr><td>The Number Is: 4</td></tr>
    </table>
    

    I will point out that your solution has many of the same issues with 'content' being an immutable string as those described in the low scoring posts to this question.

License under CC-BY-SA with attribution


Content dated before 6/26/2020 9:53 AM