zoaz
zoaz

Reputation: 2099

Convert IHtmlContent/TagBuilder to string in C#

I am using ASP.NET 5. I need to convert IHtmlContent to String

IIHtmlContent is part of the ASP.NET 5 Microsoft.AspNet.Html.Abstractions namespace and is an interface that TagBuilder implements

Simplified I have the following method

public static IHtmlContent GetContent()
{
    return new HtmlString("<tag>blah</tag>");
}

When I reference it

string output = GetContent().ToString();

I get the following output for GetContent()

"Microsoft.AspNet.Mvc.Rendering.TagBuilder" 

and not

<tag>blah</tag>

which I want

I also tried using StringBuilder

StringBuilder html = new StringBuilder();
html.Append(GetContent());

but it also appends the same namespace and not the string value

I tried to cast it to TagBuilder

TagBuilder content = (TagBuilder)GetContent();

but TagBuilder doesn't have a method that converts to string

How do I convert IHtmlContent or TagBuilder to a string?

Upvotes: 48

Views: 37905

Answers (5)

Tom
Tom

Reputation: 111

Here's an extension method so you can use it like ToString().

    public static string ToHtmlString(this IHtmlContent content)
    {
        if (content is HtmlString htmlString)
        {
            return htmlString.Value;
        }

        using (var writer = new StringWriter())
        {
            content.WriteTo(writer, HtmlEncoder.Default);
            return writer.ToString();
        }
    }

Upvotes: 2

vulcan raven
vulcan raven

Reputation: 33572

ASP.NET Core actually introduced handful of careful optimizations. If you are building an HTML extension method, then the most efficient way is to avoid string:

public static IHtmlContent GetContent(this IHtmlHelper helper)
{
    var content = new HtmlContentBuilder()
                     .AppendHtml("<ol class='content-body'><li>")
                     .AppendHtml(helper.ActionLink("Home", "Index", "Home"))
                     .AppendHtml("</li>");

    if(SomeCondition())
    {
        content.AppendHtml(@"<div>
            Note `HtmlContentBuilder.AppendHtml()` is Mutable
            as well as Fluent/Chainable.
        </div>");
    }

    return content;
}

Finally in the razor view, we don't even need @Html.Raw(Html.GetContent()) anymore (which used to be required in ASP.NET MVC 5) - not valid based on Lukáš Kmoch comment below: ASP.NET MVC 5 has type MvcHtmlString. You don't need to use Html.Raw()

just calling @Html.GetContent() is sufficient and Razor will take care of all the escaping business.

Upvotes: 23

cygnim
cygnim

Reputation: 2035

If all you need to do is output the contents as a string, just add this method and pass your IHtmlContent object as a parameter to get the string output:

public static string GetString(IHtmlContent content)
{
    using (var writer = new System.IO.StringWriter())
    {        
        content.WriteTo(writer, HtmlEncoder.Default);
        return writer.ToString();
    } 
}     

Upvotes: 67

workingbird
workingbird

Reputation: 77

there is a sample: https://github.com/aspnet/Mvc/blob/release/2.2/test/Microsoft.AspNetCore.Mvc.Views.TestCommon/HtmlContentUtilities.cs

public static string HtmlContentToString(IHtmlContent content, HtmlEncoder encoder = null)
        {
            if (encoder == null)
            {
                encoder = new HtmlTestEncoder();
            }

            using (var writer = new StringWriter())
            {
                content.WriteTo(writer, encoder);
                return writer.ToString();
            }
        }

Upvotes: 0

devfric
devfric

Reputation: 7512

Adding to the answer above:

The new instance of the HtmlEncoder doesn't work in ASP.NET Core RTM as the Microsoft.Extensions.WebEncoders namespace was removed and the new HtmlEncoder class is moved to a new namespace System.Text.Encodings.Web, but this class is now written as an abstract and sealed class so you can't create a new instance or a derived class from it.

Pass HtmlEncoder.Default to the method and it will work

public static string GetString(IHtmlContent content)
{
    var writer = new System.IO.StringWriter();
    content.WriteTo(writer, HtmlEncoder.Default);
    return writer.ToString();
}

Upvotes: 28

Related Questions